Merge commit 'e458e16debbc9068c839ce918b2e039d7efefaed' into HEAD

Change-Id: If5aaf83103dc48a2efa6c242e55e78da18bec6d2
diff --git a/Android.mk b/Android.mk
index 9829818..e6670f3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,31 +1,15 @@
+LOCAL_PATH := $(call my-dir)
 # TODO:  Find a better way to separate build configs for ADP vs non-ADP devices
 ifneq ($(TARGET_BOARD_AUTO),true)
-  ifneq ($(filter msm8084 msm8x84,$(TARGET_BOARD_PLATFORM)),)
-    #This is for 8084 based platforms
-    include $(call all-named-subdir-makefiles,msm8084)
-  else
-    ifneq ($(filter msm8226 msm8x26,$(TARGET_BOARD_PLATFORM)),)
-      include $(call all-named-subdir-makefiles,msm8226)
-    else
-      ifneq ($(filter msm8960,$(TARGET_BOARD_PLATFORM)),)
-        include $(call all-named-subdir-makefiles,msm8960)
-      else
-        ifneq ($(filter msm8994 msm8992,$(TARGET_BOARD_PLATFORM)),)
-          include $(call all-named-subdir-makefiles,msm8994)
-        else
-          ifneq ($(filter msm8909,$(TARGET_BOARD_PLATFORM)),)
-            include $(call all-named-subdir-makefiles,msm8909)
-          else
-            ifneq ($(filter msm8996,$(TARGET_BOARD_PLATFORM)),)
-              include $(call all-named-subdir-makefiles,msm8996)
-            else
-              ifneq ($(filter msm8998,$(TARGET_BOARD_PLATFORM)),)
-                include $(call all-named-subdir-makefiles,msm8998)
-              endif
-            endif
-          endif
-        endif
-      endif
-    endif
-  endif
+
+ifneq ($(filter msm8x84,$(TARGET_BOARD_PLATFORM)),)
+  include $(call all-named-subdir-makefiles,msm8084)
+else ifneq ($(filter msm8x26,$(TARGET_BOARD_PLATFORM)),)
+  include $(call all-named-subdir-makefiles,msm8226)
+else ifneq ($(filter msm8992,$(TARGET_BOARD_PLATFORM)),)
+  include $(call all-named-subdir-makefiles,msm8994)
+else ifneq ($(wildcard $(LOCAL_PATH)/$(TARGET_BOARD_PLATFORM)),)
+  include $(call all-named-subdir-makefiles,$(TARGET_BOARD_PLATFORM))
+endif
+
 endif
diff --git a/msm8909/libgralloc/alloc_controller.cpp b/msm8909/libgralloc/alloc_controller.cpp
index 64a0824..c7ba7c9 100644
--- a/msm8909/libgralloc/alloc_controller.cpp
+++ b/msm8909/libgralloc/alloc_controller.cpp
@@ -143,18 +143,13 @@
     if (format <= HAL_PIXEL_FORMAT_BGRA_8888) {
         aligned_w = ALIGN(width, 32);
         aligned_h = ALIGN(height, 32);
-        // Don't add any additional padding if debug.gralloc.map_fb_memory
-        // is enabled
-        char property[PROPERTY_VALUE_MAX];
-        if((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
-           (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
-           (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
-              return;
-        }
 
         int bpp = 4;
         switch(format)
         {
+            case HAL_PIXEL_FORMAT_RGBA_FP16:
+                bpp = 8;
+                break;
             case HAL_PIXEL_FORMAT_RGB_888:
                 bpp = 3;
                 break;
@@ -412,9 +407,13 @@
     unsigned int size = 0;
 
     switch (format) {
+        case HAL_PIXEL_FORMAT_RGBA_FP16:
+            size = alignedw * alignedh * 8;
+            break;
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_RGBX_8888:
         case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
             size = alignedw * alignedh * 4;
             break;
         case HAL_PIXEL_FORMAT_RGB_888:
diff --git a/msm8909/libgralloc/gpu.cpp b/msm8909/libgralloc/gpu.cpp
index 49274d0..b95077f 100644
--- a/msm8909/libgralloc/gpu.cpp
+++ b/msm8909/libgralloc/gpu.cpp
@@ -313,22 +313,9 @@
         return -EINVAL;
     size = (bufferSize >= size)? bufferSize : size;
 
-    bool useFbMem = false;
-    char property[PROPERTY_VALUE_MAX];
-    if((usage & GRALLOC_USAGE_HW_FB) &&
-       (property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
-       (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
-        (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
-        useFbMem = true;
-    }
-
     int err = 0;
-    if(useFbMem) {
-        err = gralloc_alloc_framebuffer(usage, pHandle);
-    } else {
-        err = gralloc_alloc_buffer(size, usage, pHandle, bufferType,
-                                   grallocFormat, alignedw, alignedh);
-    }
+    err = gralloc_alloc_buffer(size, usage, pHandle, bufferType,
+                               grallocFormat, alignedw, alignedh);
 
     if (err < 0) {
         return err;
diff --git a/msm8909/libmemtrack/kgsl.c b/msm8909/libmemtrack/kgsl.c
index 01b487f..ce6a035 100644
--- a/msm8909/libmemtrack/kgsl.c
+++ b/msm8909/libmemtrack/kgsl.c
@@ -48,7 +48,6 @@
     FILE *fp;
     char line[1024];
     char tmp[128];
-    bool is_surfaceflinger = false;
     size_t accounted_size = 0;
     size_t unaccounted_size = 0;
 
@@ -59,16 +58,6 @@
         return 0;
     }
 
-    snprintf(tmp, sizeof(tmp), "/proc/%d/cmdline", pid);
-    fp = fopen(tmp, "r");
-    if (fp != NULL) {
-        if (fgets(line, sizeof(line), fp)) {
-            if (strcmp(line, "/system/bin/surfaceflinger") == 0)
-                is_surfaceflinger = true;
-        }
-        fclose(fp);
-    }
-
     memcpy(records, record_templates,
            sizeof(struct memtrack_record) * allocated_records);
 
@@ -83,37 +72,61 @@
      * count the entry as accounted else count the entry as unaccounted.
      */
     while (1) {
-        unsigned long size;
+        unsigned long size, mapsize;
         char line_type[7];
-        char flags[7];
+        char flags[8];
         char line_usage[19];
-        int ret;
+        int ret, egl_surface_count = 0, egl_image_count = 0;
 
         if (fgets(line, sizeof(line), fp) == NULL) {
             break;
         }
 
         /* Format:
-         *  gpuaddr useraddr     size    id flags       type            usage sglen
-         * 545ba000 545ba000     4096     1 ----pY     gpumem      arraybuffer     1
+         *  gpuaddr useraddr     size    id  flags       type            usage  sglen  mapsize  egLsrf  egLimg
+         * 545ba000 545ba000     4096     1  -----pY     gpumem      arraybuffer     1     4096      0       0
          */
-        ret = sscanf(line, "%*x %*x %lu %*d %6s %6s %18s %*d\n",
-                     &size, flags, line_type, line_usage);
-        if (ret != 4) {
+        ret = sscanf(line, "%*x %*x %lu %*d %6s %6s %18s %*d %lu %6d %6d\n",
+                     &size, flags, line_type, line_usage, &mapsize,
+                     &egl_surface_count, &egl_image_count);
+        if (ret != 7) {
             continue;
         }
 
+        if (size == 0) {
+            fclose(fp);
+            return -EINVAL;
+        }
+
+        if (unaccounted_size + size < size) {
+            fclose(fp);
+            return -ERANGE;
+        }
+
         if (type == MEMTRACK_TYPE_GL && strcmp(line_type, "gpumem") == 0) {
 
-            if (flags[5] == 'Y')
-                accounted_size += size;
-            else
-                unaccounted_size += size;
+            if (flags[6] == 'Y') {
+                if (accounted_size + mapsize < accounted_size) {
+                    fclose(fp);
+                    return -ERANGE;
+                }
+                accounted_size += mapsize;
 
-        } else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, "ion") == 0) {
-            if (!is_surfaceflinger || strcmp(line_usage, "egl_image") != 0) {
+                if (mapsize > size) {
+                    fclose(fp);
+                    return -EINVAL;
+                }
+                unaccounted_size += size - mapsize;
+            } else {
                 unaccounted_size += size;
             }
+        } else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, "ion") == 0) {
+            if (strcmp(line_usage, "egl_surface") == 0) {
+                unaccounted_size += size;
+            }
+            else if (egl_surface_count == 0) {
+                unaccounted_size += size / (egl_image_count ? egl_image_count : 1);
+            }
         }
     }
 
diff --git a/msm8994/libgralloc/mapper.cpp b/msm8994/libgralloc/mapper.cpp
index 0b091fb..8df761e 100644
--- a/msm8994/libgralloc/mapper.cpp
+++ b/msm8994/libgralloc/mapper.cpp
@@ -73,7 +73,7 @@
                   hnd, hnd->fd_metadata, strerror(errno));
             return -errno;
         }
-        hnd->base_metadata = uint64_t(mappedAddress) + hnd->offset_metadata;
+        hnd->base_metadata = uint64_t(mappedAddress);
     }
     return 0;
 }
@@ -104,7 +104,7 @@
             return -errno;
         }
 
-        hnd->base = uint64_t(mappedAddress) + hnd->offset;
+        hnd->base = uint64_t(mappedAddress);
     } else {
         // Cannot map secure buffers or framebuffers, but still need to map
         // metadata for secure buffers.
diff --git a/msm8996/libgralloc/mapper.cpp b/msm8996/libgralloc/mapper.cpp
index 2ecb491..77e761d 100644
--- a/msm8996/libgralloc/mapper.cpp
+++ b/msm8996/libgralloc/mapper.cpp
@@ -73,7 +73,7 @@
                   hnd, hnd->fd_metadata, strerror(errno));
             return -errno;
         }
-        hnd->base_metadata = uint64_t(mappedAddress) + hnd->offset_metadata;
+        hnd->base_metadata = uint64_t(mappedAddress);
     }
     return 0;
 }
@@ -104,7 +104,7 @@
             return -errno;
         }
 
-        hnd->base = uint64_t(mappedAddress) + hnd->offset;
+        hnd->base = uint64_t(mappedAddress);
     } else {
         // Cannot map secure buffers or framebuffers, but still need to map
         // metadata for secure buffers.
diff --git a/msm8996/libgralloc1/gr_buf_mgr.cpp b/msm8996/libgralloc1/gr_buf_mgr.cpp
index f9aef19..1c632a1 100644
--- a/msm8996/libgralloc1/gr_buf_mgr.cpp
+++ b/msm8996/libgralloc1/gr_buf_mgr.cpp
@@ -58,7 +58,7 @@
 
 gralloc1_error_t BufferManager::CreateBufferDescriptor(
     gralloc1_buffer_descriptor_t *descriptor_id) {
-  std::lock_guard<std::mutex> lock(locker_);
+  std::lock_guard<std::mutex> lock(descriptor_lock_);
   auto descriptor = std::make_shared<BufferDescriptor>();
   descriptors_map_.emplace(descriptor->GetId(), descriptor);
   *descriptor_id = descriptor->GetId();
@@ -67,7 +67,7 @@
 
 gralloc1_error_t BufferManager::DestroyBufferDescriptor(
     gralloc1_buffer_descriptor_t descriptor_id) {
-  std::lock_guard<std::mutex> lock(locker_);
+  std::lock_guard<std::mutex> lock(descriptor_lock_);
   const auto descriptor = descriptors_map_.find(descriptor_id);
   if (descriptor == descriptors_map_.end()) {
     return GRALLOC1_ERROR_BAD_DESCRIPTOR;
@@ -93,6 +93,7 @@
   bool test_allocate = !out_buffers;
 
   // Validate descriptors
+  std::lock_guard<std::mutex> descriptor_lock(descriptor_lock_);
   std::vector<std::shared_ptr<BufferDescriptor>> descriptors;
   for (uint32_t i = 0; i < num_descriptors; i++) {
     const auto map_descriptor = descriptors_map_.find(descriptor_ids[i]);
@@ -121,6 +122,7 @@
     return status;
   }
 
+  std::lock_guard<std::mutex> buffer_lock(buffer_lock_);
   if (shared && (max_buf_index >= 0)) {
     // Allocate one and duplicate/copy the handles for each descriptor
     if (AllocateBuffer(*descriptors[UINT(max_buf_index)], &out_buffers[max_buf_index])) {
@@ -183,7 +185,7 @@
                                                    descriptor.GetConsumerUsage());
   out_hnd->id = ++next_id_;
   // TODO(user): Base address of shared handle and ion handles
-  RegisterHandle(out_hnd, -1, -1);
+  RegisterHandleLocked(out_hnd, -1, -1);
   *outbuffer = out_hnd;
 }
 
@@ -208,14 +210,14 @@
   return GRALLOC1_ERROR_NONE;
 }
 
-void BufferManager::RegisterHandle(const private_handle_t *hnd,
-                                   int ion_handle,
-                                   int ion_handle_meta) {
+void BufferManager::RegisterHandleLocked(const private_handle_t *hnd,
+                                         int ion_handle,
+                                         int ion_handle_meta) {
   auto buffer = std::make_shared<Buffer>(hnd, ion_handle, ion_handle_meta);
   handles_map_.emplace(std::make_pair(hnd, buffer));
 }
 
-gralloc1_error_t BufferManager::ImportHandle(private_handle_t* hnd) {
+gralloc1_error_t BufferManager::ImportHandleLocked(private_handle_t *hnd) {
   ALOGD_IF(DEBUG, "Importing handle:%p id: %" PRIu64, hnd, hnd->id);
   int ion_handle = allocator_->ImportBuffer(hnd->fd);
   if (ion_handle < 0) {
@@ -231,12 +233,12 @@
   // Set base pointers to NULL since the data here was received over binder
   hnd->base = 0;
   hnd->base_metadata = 0;
-  RegisterHandle(hnd, ion_handle, ion_handle_meta);
+  RegisterHandleLocked(hnd, ion_handle, ion_handle_meta);
   return GRALLOC1_ERROR_NONE;
 }
 
 std::shared_ptr<BufferManager::Buffer>
-BufferManager::GetBufferFromHandle(const private_handle_t *hnd) {
+BufferManager::GetBufferFromHandleLocked(const private_handle_t *hnd) {
   if (hnd->flags & private_handle_t::PRIV_FLAGS_CLIENT_ALLOCATED) {
     return nullptr;
   }
@@ -271,18 +273,18 @@
 }
 
 gralloc1_error_t BufferManager::RetainBuffer(private_handle_t const *hnd) {
-  std::lock_guard<std::mutex> lock(locker_);
   if (hnd->flags & private_handle_t::PRIV_FLAGS_CLIENT_ALLOCATED) {
     return GRALLOC1_ERROR_NONE;
   }
   ALOGD_IF(DEBUG, "Retain buffer handle:%p id: %" PRIu64, hnd, hnd->id);
   gralloc1_error_t err = GRALLOC1_ERROR_NONE;
-  auto buf = GetBufferFromHandle(hnd);
+  std::lock_guard<std::mutex> lock(buffer_lock_);
+  auto buf = GetBufferFromHandleLocked(hnd);
   if (buf != nullptr) {
     buf->IncRef();
   } else {
     private_handle_t *handle = const_cast<private_handle_t *>(hnd);
-    err = ImportHandle(handle);
+    err = ImportHandleLocked(handle);
   }
   return err;
 }
@@ -291,9 +293,9 @@
   if (hnd->flags & private_handle_t::PRIV_FLAGS_CLIENT_ALLOCATED) {
     return GRALLOC1_ERROR_NONE;
   }
-  std::lock_guard<std::mutex> lock(locker_);
   ALOGD_IF(DEBUG, "Release buffer handle:%p id: %" PRIu64, hnd, hnd->id);
-  auto buf = GetBufferFromHandle(hnd);
+  std::lock_guard<std::mutex> lock(buffer_lock_);
+  auto buf = GetBufferFromHandleLocked(hnd);
   if (buf == nullptr) {
     ALOGE("Could not find handle: %p id: %" PRIu64, hnd, hnd->id);
     return GRALLOC1_ERROR_BAD_HANDLE;
@@ -310,7 +312,7 @@
 gralloc1_error_t BufferManager::LockBuffer(const private_handle_t *hnd,
                                            gralloc1_producer_usage_t prod_usage,
                                            gralloc1_consumer_usage_t cons_usage) {
-  std::lock_guard<std::mutex> lock(locker_);
+  std::lock_guard<std::mutex> lock(buffer_lock_);
   gralloc1_error_t err = GRALLOC1_ERROR_NONE;
   ALOGD_IF(DEBUG, "LockBuffer buffer handle:%p id: %" PRIu64, hnd, hnd->id);
 
@@ -324,7 +326,7 @@
     err = MapBuffer(hnd);
   }
 
-  auto buf = GetBufferFromHandle(hnd);
+  auto buf = GetBufferFromHandleLocked(hnd);
   if (buf == nullptr) {
     return GRALLOC1_ERROR_BAD_HANDLE;
   }
@@ -352,11 +354,11 @@
 }
 
 gralloc1_error_t BufferManager::UnlockBuffer(const private_handle_t *handle) {
-  std::lock_guard<std::mutex> lock(locker_);
+  std::lock_guard<std::mutex> lock(buffer_lock_);
   gralloc1_error_t status = GRALLOC1_ERROR_NONE;
 
   private_handle_t *hnd = const_cast<private_handle_t *>(handle);
-  auto buf = GetBufferFromHandle(hnd);
+  auto buf = GetBufferFromHandleLocked(hnd);
   if (buf == nullptr) {
     return GRALLOC1_ERROR_BAD_HANDLE;
   }
@@ -481,14 +483,14 @@
   int buffer_type = GetBufferType(gralloc_format);
   allocator_->GetBufferSizeAndDimensions(descriptor, &size, &alignedw, &alignedh);
   size = (bufferSize >= size) ? bufferSize : size;
-  size = size * layer_count;
 
   int err = 0;
   int flags = 0;
   auto page_size = UINT(getpagesize());
   AllocData data;
   data.align = GetDataAlignment(format, prod_usage, cons_usage);
-  data.size = ALIGN(size, data.align);
+  size = ALIGN(size, data.align) * layer_count;
+  data.size = size;
   data.handle = (uintptr_t) handle;
   data.uncached = allocator_->UseUncached(prod_usage, cons_usage);
 
@@ -537,7 +539,7 @@
   ColorSpace_t colorSpace = ITU_R_601;
   setMetaData(hnd, UPDATE_COLOR_SPACE, reinterpret_cast<void *>(&colorSpace));
   *handle = hnd;
-  RegisterHandle(hnd, data.ion_handle, e_data.ion_handle);
+  RegisterHandleLocked(hnd, data.ion_handle, e_data.ion_handle);
   ALOGD_IF(DEBUG, "Allocated buffer handle: %p id: %" PRIu64, hnd, hnd->id);
   if (DEBUG) {
     private_handle_t::Dump(hnd);
diff --git a/msm8996/libgralloc1/gr_buf_mgr.h b/msm8996/libgralloc1/gr_buf_mgr.h
index 738385d..4476eaf 100644
--- a/msm8996/libgralloc1/gr_buf_mgr.h
+++ b/msm8996/libgralloc1/gr_buf_mgr.h
@@ -54,7 +54,7 @@
   gralloc1_error_t CallBufferDescriptorFunction(gralloc1_buffer_descriptor_t descriptor_id,
                                                 void (BufferDescriptor::*member)(Args...),
                                                 Args... args) {
-    std::lock_guard<std::mutex> lock(locker_);
+    std::lock_guard<std::mutex> lock(descriptor_lock_);
     const auto map_descriptor = descriptors_map_.find(descriptor_id);
     if (map_descriptor == descriptors_map_.end()) {
       return GRALLOC1_ERROR_BAD_DESCRIPTOR;
@@ -83,10 +83,10 @@
                           buffer_handle_t *out_buffer);
 
   // Imports the ion fds into the current process. Returns an error for invalid handles
-  gralloc1_error_t ImportHandle(private_handle_t* hnd);
+  gralloc1_error_t ImportHandleLocked(private_handle_t *hnd);
 
   // Creates a Buffer from the valid private handle and adds it to the map
-  void RegisterHandle(const private_handle_t *hnd, int ion_handle, int ion_handle_meta);
+  void RegisterHandleLocked(const private_handle_t *hnd, int ion_handle, int ion_handle_meta);
 
   // Wrapper structure over private handle
   // Values associated with the private handle
@@ -115,12 +115,13 @@
   gralloc1_error_t FreeBuffer(std::shared_ptr<Buffer> buf);
 
   // Get the wrapper Buffer object from the handle, returns nullptr if handle is not found
-  std::shared_ptr<Buffer> GetBufferFromHandle(const private_handle_t *hnd);
+  std::shared_ptr<Buffer> GetBufferFromHandleLocked(const private_handle_t *hnd);
 
   bool map_fb_mem_ = false;
   bool ubwc_for_fb_ = false;
   Allocator *allocator_ = NULL;
-  std::mutex locker_;
+  std::mutex buffer_lock_;
+  std::mutex descriptor_lock_;
   // TODO(user): The private_handle_t is used as a key because the unique ID generated
   // from next_id_ is not unique across processes. The correct way to resolve this would
   // be to use the allocator over hwbinder
diff --git a/msm8996/libgralloc1/gr_device_impl.cpp b/msm8996/libgralloc1/gr_device_impl.cpp
index 33e6cd5..a6a7f3d 100644
--- a/msm8996/libgralloc1/gr_device_impl.cpp
+++ b/msm8996/libgralloc1/gr_device_impl.cpp
@@ -174,25 +174,13 @@
 }
 
 gralloc1_error_t GrallocImpl::Dump(gralloc1_device_t *device, uint32_t *out_size,
-                                   char *out_buffer) {
+                                   char *out_buffer __unused) {
   if (!device) {
     ALOGE("Gralloc Error : device=%p", (void *)device);
     return GRALLOC1_ERROR_BAD_DESCRIPTOR;
   }
-  const size_t max_dump_size = 8192;
-  if (out_buffer == nullptr) {
-    *out_size = max_dump_size;
-  } else {
-    std::ostringstream os;
-    os << "-------------------------------" << std::endl;
-    os << "QTI gralloc dump:" << std::endl;
-    os << "-------------------------------" << std::endl;
-    GrallocImpl const *dev = GRALLOC_IMPL(device);
-    dev->buf_mgr_->Dump(&os);
-    os << "-------------------------------" << std::endl;
-    auto copied = os.str().copy(out_buffer, std::min(os.str().size(), max_dump_size), 0);
-    *out_size = UINT(copied);
-  }
+  // nothing to dump
+  *out_size = 0;
 
   return GRALLOC1_ERROR_NONE;
 }
diff --git a/msm8996/sdm/libs/core/display_base.cpp b/msm8996/sdm/libs/core/display_base.cpp
index ea4aede..7d3f089 100644
--- a/msm8996/sdm/libs/core/display_base.cpp
+++ b/msm8996/sdm/libs/core/display_base.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2017, 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:
@@ -578,6 +578,12 @@
   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.at(layer_index);
+
+    if (layer == NULL || layer->input_buffer == NULL) {
+      DumpImpl::AppendString(buffer, length, "\n|                                                                  Invalid Layer                                                                                  |");  //NOLINT
+      DumpImpl::AppendString(buffer, length, newline);
+      continue;
+    }
     LayerBuffer *input_buffer = layer->input_buffer;
     HWLayerConfig &layer_config = hw_layers_.config[i];
     HWRotatorSession &hw_rotator_session = layer_config.hw_rotator_session;
diff --git a/msm8996/sdm/libs/hwc2/hwc_display.cpp b/msm8996/sdm/libs/hwc2/hwc_display.cpp
index 146d12b..10b2220 100644
--- a/msm8996/sdm/libs/hwc2/hwc_display.cpp
+++ b/msm8996/sdm/libs/hwc2/hwc_display.cpp
@@ -364,15 +364,6 @@
       layer_stack_.flags.skip_present = true;
     }
 
-
-    if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Cursor) {
-      // Currently we support only one HWCursor & only at top most z-order
-      if ((*layer_set_.rbegin())->GetId() == hwc_layer->GetId()) {
-        layer->flags.cursor = true;
-        layer_stack_.flags.cursor_present = true;
-      }
-    }
-
     // TODO(user): Move to a getter if this is needed at other places
     hwc_rect_t scaled_display_frame = {INT(layer->dst_rect.left), INT(layer->dst_rect.top),
                                        INT(layer->dst_rect.right), INT(layer->dst_rect.bottom)};
@@ -1391,8 +1382,26 @@
     return HWC2::Error::None;
   }
 
-  // TODO(user): Validate layer
-  // TODO(user): Check if we're in a validate/present cycle
+  HWCLayer *hwc_layer = GetHWCLayer(layer);
+  if (hwc_layer == nullptr) {
+    return HWC2::Error::BadLayer;
+  }
+  if (hwc_layer->GetDeviceSelectedCompositionType() != HWC2::Composition::Cursor) {
+    return HWC2::Error::BadLayer;
+  }
+  if (validated_ == true) {
+    // the device is currently in the middle of the validate/present sequence,
+    // cannot set the Position(as per HWC2 spec)
+    return HWC2::Error::NotValidated;
+  }
+
+  DisplayState state;
+  if (display_intf_->GetDisplayState(&state) == kErrorNone) {
+    if (state != kStateOn) {
+      return HWC2::Error::None;
+    }
+  }
+
 
   auto error = display_intf_->SetCursorPosition(x, y);
   if (error != kErrorNone) {
diff --git a/msm8998/gpu_tonemapper/Android.mk b/msm8998/gpu_tonemapper/Android.mk
index a5b5a8e..fcb66cb 100644
--- a/msm8998/gpu_tonemapper/Android.mk
+++ b/msm8998/gpu_tonemapper/Android.mk
@@ -2,6 +2,7 @@
 include $(LOCAL_PATH)/../common.mk
 
 include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE       := true
 LOCAL_COPY_HEADERS_TO     := $(common_header_export_path)
 LOCAL_COPY_HEADERS        := TonemapFactory.h Tonemapper.h
 LOCAL_VENDOR_MODULE       := true
@@ -13,7 +14,7 @@
 LOCAL_MODULE_TAGS         := optional
 LOCAL_C_INCLUDES          := $(TARGET_OUT_HEADERS)/qcom/display/
 LOCAL_C_INCLUDES          += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
-LOCAL_SHARED_LIBRARIES    := libEGL libGLESv2 libui libutils liblog
+LOCAL_SHARED_LIBRARIES    := libEGL libGLESv2 libGLESv3 libui libutils liblog
 
 LOCAL_CFLAGS              := $(version_flag) -Wno-missing-field-initializers -Wall \
                              -Wno-unused-parameter -std=c++11 -DLOG_TAG=\"GPU_TONEMAPPER\"
diff --git a/msm8998/include/Android.mk b/msm8998/include/Android.mk
index a72d5c3..455436b 100644
--- a/msm8998/include/Android.mk
+++ b/msm8998/include/Android.mk
@@ -21,4 +21,5 @@
                                  $(display_top)/sdm/include \
                                  $(display_top)/libgralloc1
 
+LOCAL_EXPORT_HEADER_LIBRARY_HEADERS := libhardware_headers
 include $(BUILD_HEADER_LIBRARY)
diff --git a/msm8998/libgralloc1/gr_adreno_info.cpp b/msm8998/libgralloc1/gr_adreno_info.cpp
index 59a6f5f..1c833ed 100644
--- a/msm8998/libgralloc1/gr_adreno_info.cpp
+++ b/msm8998/libgralloc1/gr_adreno_info.cpp
@@ -54,8 +54,7 @@
     *reinterpret_cast<void **>(&LINK_adreno_get_gpu_pixel_alignment) =
         ::dlsym(libadreno_utils_, "get_gpu_pixel_alignment");
   } else {
-    ALOGE(" Failed to load libadreno_utils.so");
-    return false;
+    ALOGW(" Failed to load libadreno_utils.so");
   }
 
   // Check if the overriding property debug.gralloc.gfx_ubwc_disable_
@@ -141,6 +140,8 @@
         width, height, format, 0, raster_mode, padding_threshold,
         reinterpret_cast<int *>(aligned_w), reinterpret_cast<int *>(aligned_h), &bytesPerPixel);
   } else {
+    *aligned_w = (unsigned int)ALIGN(width, 32);
+    *aligned_h = (unsigned int)ALIGN(height, 32);
     ALOGW("%s: Warning!! compute_compressedfmt_aligned_width_and_height not found", __FUNCTION__);
   }
 }
diff --git a/msm8998/libgralloc1/gr_allocator.cpp b/msm8998/libgralloc1/gr_allocator.cpp
index 589f772..899ba8e 100644
--- a/msm8998/libgralloc1/gr_allocator.cpp
+++ b/msm8998/libgralloc1/gr_allocator.cpp
@@ -84,9 +84,7 @@
   }
 
   adreno_helper_ = new AdrenoMemInfo();
-  if (!adreno_helper_->Init()) {
-    return false;
-  }
+  adreno_helper_->Init();
 
   return true;
 }
diff --git a/msm8998/liblight/Android.mk b/msm8998/liblight/Android.mk
index eec6bb8..94bf835 100644
--- a/msm8998/liblight/Android.mk
+++ b/msm8998/liblight/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_CFLAGS := -DLOG_TAG=\"qdlights\"
 LOCAL_CLANG  := true
 LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)
+LOCAL_HEADER_LIBRARIES := libhardware_headers
 LOCAL_MODULE_TAGS := optional
 LOCAL_VENDOR_MODULE := true
 
diff --git a/msm8998/libmemtrack/Android.mk b/msm8998/libmemtrack/Android.mk
index d4014bb..2535ee0 100644
--- a/msm8998/libmemtrack/Android.mk
+++ b/msm8998/libmemtrack/Android.mk
@@ -20,10 +20,10 @@
 
 LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_VENDOR_MODULE := true
-LOCAL_C_INCLUDES += hardware/libhardware/include
 LOCAL_CFLAGS := -Wconversion -Wall -Werror -Wno-sign-conversion
 LOCAL_CLANG  := true
 LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_SRC_FILES := memtrack_msm.c kgsl.c
 LOCAL_MODULE := memtrack.$(TARGET_BOARD_PLATFORM)
+LOCAL_HEADER_LIBRARIES := libhardware_headers
 include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8998/libqdutils/qdMetaData.cpp b/msm8998/libqdutils/qdMetaData.cpp
index 783006d..0860c81 100644
--- a/msm8998/libqdutils/qdMetaData.cpp
+++ b/msm8998/libqdutils/qdMetaData.cpp
@@ -37,8 +37,8 @@
 
 static int validateAndMap(private_handle_t* handle) {
     if (private_handle_t::validate(handle)) {
-        ALOGE("%s: Private handle is invalid - handle:%p id: %" PRIu64,
-                __func__, handle, handle->id);
+        ALOGE("%s: Private handle is invalid - handle:%p",
+                __func__, handle);
         return -1;
     }
     if (handle->fd_metadata == -1) {
diff --git a/msm8998/libqservice/IQService.cpp b/msm8998/libqservice/IQService.cpp
index 2d0cbfb..d45a141 100644
--- a/msm8998/libqservice/IQService.cpp
+++ b/msm8998/libqservice/IQService.cpp
@@ -25,8 +25,8 @@
 #include <binder/IBinder.h>
 #include <binder/IInterface.h>
 #include <binder/IPCThreadState.h>
+#include <cutils/android_filesystem_config.h>
 #include <utils/Errors.h>
-#include <private/android_filesystem_config.h>
 #include <IQService.h>
 
 #define QSERVICE_DEBUG 0
diff --git a/sdm845/Android.mk b/sdm845/Android.mk
new file mode 100644
index 0000000..226e8a0
--- /dev/null
+++ b/sdm845/Android.mk
@@ -0,0 +1,21 @@
+sdm-libs := sdm/libs
+display-hals := include libqservice libqdutils $(sdm-libs)/utils $(sdm-libs)/core
+
+ifneq ($(TARGET_IS_HEADLESS), true)
+    display-hals += libcopybit liblight libmemtrack hdmi_cec \
+                    $(sdm-libs)/hwc $(sdm-libs)/hwc2 gpu_tonemapper libdrmutils
+endif
+
+ifneq ($(TARGET_USES_GRALLOC1), true)
+    display-hals += libgralloc
+else
+    display-hals += libgralloc1
+endif
+
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+    include $(call all-named-subdir-makefiles,$(display-hals))
+else
+ifneq ($(filter msm% apq%,$(TARGET_BOARD_PLATFORM)),)
+    include $(call all-named-subdir-makefiles,$(display-hals))
+endif
+endif
diff --git a/sdm845/Makefile.am b/sdm845/Makefile.am
new file mode 100644
index 0000000..781b836
--- /dev/null
+++ b/sdm845/Makefile.am
@@ -0,0 +1,5 @@
+# Makefile.am - Automake script for sdm
+
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = libqservice libqdutils libgralloc sdm/libs/utils sdm/libs/core
diff --git a/sdm845/common.mk b/sdm845/common.mk
new file mode 100644
index 0000000..88d1aee
--- /dev/null
+++ b/sdm845/common.mk
@@ -0,0 +1,74 @@
+#Common headers
+display_top := $(call my-dir)
+
+#Common C flags
+common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
+common_flags += -Wconversion -Wall -Werror -std=c++11
+ifeq ($(TARGET_IS_HEADLESS), true)
+    common_flags += -DTARGET_HEADLESS
+    LOCAL_CLANG := false
+endif
+
+ifeq ($(TARGET_USES_COLOR_METADATA), true)
+    common_flags += -DUSE_COLOR_METADATA
+endif
+
+ifeq ($(TARGET_USES_QCOM_BSP),true)
+    common_flags += -DQTI_BSP
+endif
+
+ifeq ($(ARCH_ARM_HAVE_NEON),true)
+    common_flags += -D__ARM_HAVE_NEON
+endif
+
+ifeq ($(call is-board-platform-in-list, $(MASTER_SIDE_CP_TARGET_LIST)), true)
+    common_flags += -DMASTER_SIDE_CP
+endif
+
+use_hwc2 := false
+ifeq ($(TARGET_USES_HWC2), true)
+    use_hwc2 := true
+    common_flags += -DVIDEO_MODE_DEFER_RETIRE_FENCE
+endif
+
+ifeq ($(TARGET_USES_GRALLOC1), true)
+    common_flags += -DUSE_GRALLOC1
+endif
+
+common_includes := system/core/base/include
+CHECK_VERSION_LE = $(shell if [ $(1) -le $(2) ] ; then echo true ; else echo false ; fi)
+PLATFORM_SDK_NOUGAT = 25
+ifeq "REL" "$(PLATFORM_VERSION_CODENAME)"
+ifeq ($(call CHECK_VERSION_LE, $(PLATFORM_SDK_VERSION), $(PLATFORM_SDK_NOUGAT)), true)
+version_flag := -D__NOUGAT__
+
+# These include paths are deprecated post N
+common_includes += $(display_top)/libqdutils
+common_includes += $(display_top)/libqservice
+common_includes += $(display_top)/gpu_tonemapper
+ifneq ($(TARGET_IS_HEADLESS), true)
+    common_includes += $(display_top)/libcopybit
+endif
+
+common_includes += $(display_top)/include
+common_includes += $(display_top)/sdm/include
+common_flags += -isystem $(TARGET_OUT_HEADERS)/qcom/display
+endif
+endif
+
+common_header_export_path := qcom/display
+
+#Common libraries external to display HAL
+common_libs := liblog libutils libcutils libhardware
+common_deps  :=
+kernel_includes :=
+
+ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true)
+# This check is to pick the kernel headers from the right location.
+# If the macro above is defined, we make the assumption that we have the kernel
+# available in the build tree.
+# If the macro is not present, the headers are picked from hardware/qcom/msmXXXX
+# failing which, they are picked from bionic.
+    common_deps += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+    kernel_includes += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+endif
diff --git a/sdm845/configure.ac b/sdm845/configure.ac
new file mode 100644
index 0000000..6fe7d0a
--- /dev/null
+++ b/sdm845/configure.ac
@@ -0,0 +1,57 @@
+#                                               -*- Autoconf -*-
+# configure.ac -- Autoconf script for sdm
+#
+
+# Process this file with autoconf to produce a configure script
+
+# Requires autoconf tool later than 2.61
+AC_PREREQ(2.61)
+# Initialize the display package version 1.0.0
+AC_INIT([display],1.0.0)
+# Does not strictly follow GNU Coding standards
+AM_INIT_AUTOMAKE([foreign])
+# Disables auto rebuilding of configure, Makefile.ins
+AM_MAINTAINER_MODE
+# defines some macros variable to be included by source
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+AC_SUBST([COMMON_CFLAGS], [-Wall -Werror -Wno-sign-conversion -Wconversion -DDEBUG_CALC_FPS])
+AC_SUBST([AM_CPPFLAGS], [--std=c++11])
+
+AC_ARG_WITH([core_includes],
+    AC_HELP_STRING([--with-core-includes=@<:@dir@:>@],
+       [Specify the location of the core headers]),
+    [core_incdir=$withval],
+    with_core_includes=no)
+
+if test "x$with_core_includes" != "xno"; then
+   CFLAGS="${CFLAGS} -I${core_incdir}"
+fi
+
+AC_ARG_WITH(sanitized-headers,
+   AS_HELP_STRING([--with-sanitized-headers=DIR],
+       [Specify the location of the sanitized Linux headers]),
+   [CPPFLAGS="$CPPFLAGS -idirafter $withval"])
+
+# Checks for programs.
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+AC_PROG_AWK
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+
+AC_SUBST([CFLAGS])
+AC_SUBST([CC])
+AC_CONFIG_FILES([ \
+        Makefile \
+        libqservice/Makefile \
+        libqdutils/Makefile \
+        libgralloc/Makefile \
+        sdm/libs/utils/Makefile \
+        sdm/libs/core/Makefile
+        ])
+AC_OUTPUT
\ No newline at end of file
diff --git a/sdm845/gpu_tonemapper/Android.mk b/sdm845/gpu_tonemapper/Android.mk
new file mode 100644
index 0000000..769d0ab
--- /dev/null
+++ b/sdm845/gpu_tonemapper/Android.mk
@@ -0,0 +1,27 @@
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+
+include $(CLEAR_VARS)
+LOCAL_COPY_HEADERS_TO     := $(common_header_export_path)
+LOCAL_COPY_HEADERS        := TonemapFactory.h Tonemapper.h
+include $(BUILD_COPY_HEADERS)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE              := libgpu_tonemapper
+LOCAL_VENDOR_MODULE       := true
+LOCAL_MODULE_TAGS         := optional
+LOCAL_C_INCLUDES          := $(TARGET_OUT_HEADERS)/qcom/display/
+LOCAL_C_INCLUDES          += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_SHARED_LIBRARIES    := libEGL libGLESv2 libui libutils liblog
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
+
+LOCAL_CFLAGS              := $(version_flag) -Wno-missing-field-initializers -Wall \
+                             -Wno-unused-parameter -std=c++11 -DLOG_TAG=\"GPU_TONEMAPPER\"
+
+LOCAL_SRC_FILES           := TonemapFactory.cpp \
+                             glengine.cpp \
+                             EGLImageBuffer.cpp \
+                             EGLImageWrapper.cpp \
+                             Tonemapper.cpp
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/sdm845/gpu_tonemapper/EGLImageBuffer.cpp b/sdm845/gpu_tonemapper/EGLImageBuffer.cpp
new file mode 100644
index 0000000..eeb0273
--- /dev/null
+++ b/sdm845/gpu_tonemapper/EGLImageBuffer.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EGLImageBuffer.h"
+#include <cutils/native_handle.h>
+#include <gralloc_priv.h>
+#include <ui/GraphicBuffer.h>
+#include <map>
+#include "EGLImageWrapper.h"
+#include "glengine.h"
+
+//-----------------------------------------------------------------------------
+EGLImageKHR create_eglImage(android::sp<android::GraphicBuffer> graphicBuffer)
+//-----------------------------------------------------------------------------
+{
+  bool isProtected = (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+  EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
+                    isProtected ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+                    isProtected ? EGL_TRUE : EGL_NONE, EGL_NONE};
+
+  EGLImageKHR eglImage = eglCreateImageKHR(
+      eglGetCurrentDisplay(), (EGLContext)EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+      (EGLClientBuffer)(graphicBuffer->getNativeBuffer()), attrs);
+
+  return eglImage;
+}
+
+//-----------------------------------------------------------------------------
+EGLImageBuffer::EGLImageBuffer(android::sp<android::GraphicBuffer> graphicBuffer)
+//-----------------------------------------------------------------------------
+{
+  // this->graphicBuffer = graphicBuffer;
+  this->eglImageID = create_eglImage(graphicBuffer);
+  this->width = graphicBuffer->getWidth();
+  this->height = graphicBuffer->getHeight();
+
+  textureID = 0;
+  renderbufferID = 0;
+  framebufferID = 0;
+}
+
+//-----------------------------------------------------------------------------
+EGLImageBuffer::~EGLImageBuffer()
+//-----------------------------------------------------------------------------
+{
+  if (textureID != 0) {
+    GL(glDeleteTextures(1, &textureID));
+    textureID = 0;
+  }
+
+  if (renderbufferID != 0) {
+    GL(glDeleteRenderbuffers(1, &renderbufferID));
+    renderbufferID = 0;
+  }
+
+  if (framebufferID != 0) {
+    GL(glDeleteFramebuffers(1, &framebufferID));
+    framebufferID = 0;
+  }
+
+  // Delete the eglImage
+  if (eglImageID != 0)
+  {
+      eglDestroyImageKHR(eglGetCurrentDisplay(), eglImageID);
+      eglImageID = 0;
+  }
+}
+
+//-----------------------------------------------------------------------------
+int EGLImageBuffer::getWidth()
+//-----------------------------------------------------------------------------
+{
+  return width;
+}
+
+//-----------------------------------------------------------------------------
+int EGLImageBuffer::getHeight()
+//-----------------------------------------------------------------------------
+{
+  return height;
+}
+
+//-----------------------------------------------------------------------------
+unsigned int EGLImageBuffer::getTexture()
+//-----------------------------------------------------------------------------
+{
+  if (textureID == 0) {
+    bindAsTexture();
+  }
+
+  return textureID;
+}
+
+//-----------------------------------------------------------------------------
+unsigned int EGLImageBuffer::getFramebuffer()
+//-----------------------------------------------------------------------------
+{
+  if (framebufferID == 0) {
+    bindAsFramebuffer();
+  }
+
+  return framebufferID;
+}
+
+//-----------------------------------------------------------------------------
+void EGLImageBuffer::bindAsTexture()
+//-----------------------------------------------------------------------------
+{
+  if (textureID == 0) {
+    GL(glGenTextures(1, &textureID));
+    int target = 0x8D65;
+    GL(glBindTexture(target, textureID));
+    GL(glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+    GL(glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+    GL(glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+    GL(glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+
+    GL(glEGLImageTargetTexture2DOES(0x8D65, eglImageID));
+  }
+
+  GL(glBindTexture(0x8D65, textureID));
+}
+
+//-----------------------------------------------------------------------------
+void EGLImageBuffer::bindAsFramebuffer()
+//-----------------------------------------------------------------------------
+{
+  if (renderbufferID == 0) {
+    GL(glGenFramebuffers(1, &framebufferID));
+    GL(glGenRenderbuffers(1, &renderbufferID));
+
+    GL(glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID));
+    GL(glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, eglImageID));
+
+    GL(glBindFramebuffer(GL_FRAMEBUFFER, framebufferID));
+    GL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+                                 renderbufferID));
+    GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    if (result != GL_FRAMEBUFFER_COMPLETE) {
+      ALOGI("%s Framebuffer Invalid***************", __FUNCTION__);
+    }
+  }
+
+  GL(glBindFramebuffer(GL_FRAMEBUFFER, framebufferID));
+}
diff --git a/sdm845/gpu_tonemapper/EGLImageBuffer.h b/sdm845/gpu_tonemapper/EGLImageBuffer.h
new file mode 100644
index 0000000..23af573
--- /dev/null
+++ b/sdm845/gpu_tonemapper/EGLImageBuffer.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __EGLIMAGE_BUFFER_H__
+#define __EGLIMAGE_BUFFER_H__
+
+#include <cutils/native_handle.h>
+#include <gralloc_priv.h>
+#include <ui/GraphicBuffer.h>
+#include "engine.h"
+
+class EGLImageBuffer {
+  // android::sp<android::GraphicBuffer> graphicBuffer;
+  void *eglImageID;
+  int width;
+  int height;
+  uint textureID;
+  uint renderbufferID;
+  uint framebufferID;
+
+ public:
+  int getWidth();
+  int getHeight();
+  EGLImageBuffer(android::sp<android::GraphicBuffer>);
+  unsigned int getTexture();
+  unsigned int getFramebuffer();
+  void bindAsTexture();
+  void bindAsFramebuffer();
+  ~EGLImageBuffer();
+  static EGLImageBuffer *from(const private_handle_t *src);
+  static void clear();
+};
+
+#endif  //__EGLIMAGE_BUFFER_H__
\ No newline at end of file
diff --git a/sdm845/gpu_tonemapper/EGLImageWrapper.cpp b/sdm845/gpu_tonemapper/EGLImageWrapper.cpp
new file mode 100644
index 0000000..dfc16d8
--- /dev/null
+++ b/sdm845/gpu_tonemapper/EGLImageWrapper.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EGLImageWrapper.h"
+#include <cutils/native_handle.h>
+#include <gralloc_priv.h>
+#include <ui/GraphicBuffer.h>
+#include <fcntl.h>
+#include <linux/msm_ion.h>
+
+//-----------------------------------------------------------------------------
+void free_ion_cookie(int ion_fd, int cookie)
+//-----------------------------------------------------------------------------
+{
+  if (ion_fd && !ioctl(ion_fd, ION_IOC_FREE, &cookie)) {
+  } else {
+      ALOGE("ION_IOC_FREE failed: ion_fd = %d, cookie = %d", ion_fd, cookie);
+  }
+}
+
+//-----------------------------------------------------------------------------
+int get_ion_cookie(int ion_fd, int fd)
+//-----------------------------------------------------------------------------
+{
+   int cookie = fd;
+
+   struct ion_fd_data fdData;
+   memset(&fdData, 0, sizeof(fdData));
+   fdData.fd = fd;
+
+   if (ion_fd && !ioctl(ion_fd, ION_IOC_IMPORT, &fdData)) {
+        cookie = fdData.handle;
+   } else {
+        ALOGE("ION_IOC_IMPORT failed: ion_fd = %d, fd = %d", ion_fd, fd);
+   }
+
+   return cookie;
+}
+
+//-----------------------------------------------------------------------------
+EGLImageWrapper::DeleteEGLImageCallback::DeleteEGLImageCallback(int fd)
+//-----------------------------------------------------------------------------
+{
+    ion_fd = fd;
+}
+
+//-----------------------------------------------------------------------------
+void EGLImageWrapper::DeleteEGLImageCallback::operator()(int& k, EGLImageBuffer*& eglImage)
+//-----------------------------------------------------------------------------
+{
+    free_ion_cookie(ion_fd,  k);
+    if( eglImage != 0 )
+    {
+        delete eglImage;
+    }
+}
+
+//-----------------------------------------------------------------------------
+EGLImageWrapper::EGLImageWrapper()
+//-----------------------------------------------------------------------------
+{
+    eglImageBufferMap = new android::LruCache<int, EGLImageBuffer*>(32);
+    ion_fd = open("/dev/ion", O_RDONLY);
+    callback = new DeleteEGLImageCallback(ion_fd);
+    eglImageBufferMap->setOnEntryRemovedListener(callback);
+}
+
+//-----------------------------------------------------------------------------
+EGLImageWrapper::~EGLImageWrapper()
+//-----------------------------------------------------------------------------
+{
+    if( eglImageBufferMap != 0 )
+    {
+        eglImageBufferMap->clear();
+        delete eglImageBufferMap;
+        eglImageBufferMap = 0;
+    }
+
+    if( callback != 0 )
+    {
+        delete callback;
+        callback = 0;
+    }
+
+    if( ion_fd > 0 )
+    {
+        close(ion_fd);
+    }
+    ion_fd = -1;
+}
+//-----------------------------------------------------------------------------
+static EGLImageBuffer* L_wrap(const private_handle_t *src)
+//-----------------------------------------------------------------------------
+{
+    EGLImageBuffer* result = 0;
+
+    native_handle_t *native_handle = const_cast<private_handle_t *>(src);
+
+    int flags = android::GraphicBuffer::USAGE_HW_TEXTURE |
+                android::GraphicBuffer::USAGE_SW_READ_NEVER |
+                android::GraphicBuffer::USAGE_SW_WRITE_NEVER;
+
+    if (src->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+      flags |= android::GraphicBuffer::USAGE_PROTECTED;
+    }
+
+    android::sp<android::GraphicBuffer> graphicBuffer =
+        new android::GraphicBuffer(src->unaligned_width, src->unaligned_height, src->format,
+#ifndef __NOUGAT__
+                                   1, // Layer count
+#endif
+                                   flags, src->width /*src->stride*/,
+                                   native_handle, false);
+
+    result = new EGLImageBuffer(graphicBuffer);
+
+    return result;
+}
+
+//-----------------------------------------------------------------------------
+EGLImageBuffer *EGLImageWrapper::wrap(const void *pvt_handle)
+//-----------------------------------------------------------------------------
+{
+    const private_handle_t *src = static_cast<const private_handle_t *>(pvt_handle);
+
+    int ion_cookie = get_ion_cookie(ion_fd, src->fd);
+    EGLImageBuffer* eglImage = eglImageBufferMap->get(ion_cookie);
+    if( eglImage == 0 )
+    {
+        eglImage = L_wrap(src);
+        eglImageBufferMap->put(ion_cookie, eglImage);
+    }
+    else {
+        free_ion_cookie(ion_fd, ion_cookie);
+    }
+
+    return eglImage;
+}
diff --git a/sdm845/gpu_tonemapper/EGLImageWrapper.h b/sdm845/gpu_tonemapper/EGLImageWrapper.h
new file mode 100644
index 0000000..e9a4d68
--- /dev/null
+++ b/sdm845/gpu_tonemapper/EGLImageWrapper.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TONEMAPPER_EGLIMAGEWRAPPER_H__
+#define __TONEMAPPER_EGLIMAGEWRAPPER_H__
+
+#include <utils/LruCache.h>
+#include "EGLImageBuffer.h"
+
+class EGLImageWrapper {
+    private:
+        class DeleteEGLImageCallback : public android::OnEntryRemoved<int, EGLImageBuffer*>
+        {
+        private:
+          int ion_fd;
+        public:
+          DeleteEGLImageCallback(int ion_fd);
+          void operator()(int& ion_cookie, EGLImageBuffer*& eglImage);
+        };
+
+        android::LruCache<int, EGLImageBuffer *>* eglImageBufferMap;
+        DeleteEGLImageCallback* callback;
+        int ion_fd;
+
+    public:
+        EGLImageWrapper();
+        ~EGLImageWrapper();
+        EGLImageBuffer* wrap(const void *pvt_handle);
+};
+
+#endif  //__TONEMAPPER_EGLIMAGEWRAPPER_H__
diff --git a/sdm845/gpu_tonemapper/TonemapFactory.cpp b/sdm845/gpu_tonemapper/TonemapFactory.cpp
new file mode 100644
index 0000000..3233682
--- /dev/null
+++ b/sdm845/gpu_tonemapper/TonemapFactory.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TonemapFactory.h"
+#include <utils/Log.h>
+#include "Tonemapper.h"
+#include "engine.h"
+
+//----------------------------------------------------------------------------------------------------------------------------------------------------------
+Tonemapper *TonemapperFactory_GetInstance(int type, void *colorMap, int colorMapSize,
+                                          void *lutXform, int lutXformSize, bool isSecure)
+//----------------------------------------------------------------------------------------------------------------------------------------------------------
+{
+  // build the tonemapper
+  Tonemapper *tonemapper = Tonemapper::build(type, colorMap, colorMapSize, lutXform, lutXformSize, isSecure);
+
+  return tonemapper;
+}
diff --git a/sdm845/gpu_tonemapper/TonemapFactory.h b/sdm845/gpu_tonemapper/TonemapFactory.h
new file mode 100644
index 0000000..17cad40
--- /dev/null
+++ b/sdm845/gpu_tonemapper/TonemapFactory.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TONEMAPPER_TONEMAPPERFACTORY_H__
+#define __TONEMAPPER_TONEMAPPERFACTORY_H__
+
+#include "Tonemapper.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// returns an instance of Tonemapper
+Tonemapper *TonemapperFactory_GetInstance(int type, void *colorMap, int colorMapSize,
+                                          void *lutXform, int lutXformSize, bool isSecure);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  //__TONEMAPPER_TONEMAPPERFACTORY_H__
diff --git a/sdm845/gpu_tonemapper/Tonemapper.cpp b/sdm845/gpu_tonemapper/Tonemapper.cpp
new file mode 100644
index 0000000..981863d
--- /dev/null
+++ b/sdm845/gpu_tonemapper/Tonemapper.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <utils/Log.h>
+
+#include "EGLImageWrapper.h"
+#include "Tonemapper.h"
+#include "engine.h"
+#include "forward_tonemap.inl"
+#include "fullscreen_vertex_shader.inl"
+#include "rgba_inverse_tonemap.inl"
+
+//-----------------------------------------------------------------------------
+Tonemapper::Tonemapper()
+//-----------------------------------------------------------------------------
+{
+  tonemapTexture = 0;
+  lutXformTexture = 0;
+  programID = 0;
+  eglImageWrapper = new EGLImageWrapper();
+
+  lutXformScaleOffset[0] = 1.0f;
+  lutXformScaleOffset[1] = 0.0f;
+
+  tonemapScaleOffset[0] = 1.0f;
+  tonemapScaleOffset[1] = 0.0f;
+}
+
+//-----------------------------------------------------------------------------
+Tonemapper::~Tonemapper()
+//-----------------------------------------------------------------------------
+{
+  void* caller_context = engine_backup();
+  engine_bind(engineContext);
+  engine_deleteInputBuffer(tonemapTexture);
+  engine_deleteInputBuffer(lutXformTexture);
+  engine_deleteProgram(programID);
+
+  // clear EGLImage mappings
+  if (eglImageWrapper != 0) {
+    delete eglImageWrapper;
+    eglImageWrapper = 0;
+  }
+
+  engine_shutdown(engineContext);
+  // restore the caller context
+  engine_bind(caller_context);
+  engine_free_backup(caller_context);
+}
+
+//-----------------------------------------------------------------------------
+Tonemapper *Tonemapper::build(int type, void *colorMap, int colorMapSize, void *lutXform,
+                              int lutXformSize, bool isSecure)
+//-----------------------------------------------------------------------------
+{
+  if (colorMapSize <= 0) {
+      ALOGE("Invalid Color Map size = %d", colorMapSize);
+      return NULL;
+  }
+
+  // build new tonemapper
+  Tonemapper *tonemapper = new Tonemapper();
+
+  tonemapper->engineContext = engine_initialize(isSecure);
+
+  void* caller_context = engine_backup();
+  engine_bind(tonemapper->engineContext);
+
+  // load the 3d lut
+  tonemapper->tonemapTexture = engine_load3DTexture(colorMap, colorMapSize, 0);
+  tonemapper->tonemapScaleOffset[0] = ((float)(colorMapSize-1))/((float)(colorMapSize));
+  tonemapper->tonemapScaleOffset[1] = 1.0f/(2.0f*colorMapSize);
+
+  // load the non-uniform xform
+  tonemapper->lutXformTexture = engine_load1DTexture(lutXform, lutXformSize, 0);
+  bool bUseXform = (tonemapper->lutXformTexture != 0) && (lutXformSize != 0);
+  if( bUseXform )
+  {
+      tonemapper->lutXformScaleOffset[0] = ((float)(lutXformSize-1))/((float)(lutXformSize));
+      tonemapper->lutXformScaleOffset[1] = 1.0f/(2.0f*lutXformSize);
+  }
+
+  // create the program
+  const char *fragmentShaders[3];
+  int fragmentShaderCount = 0;
+  const char *version = "#version 300 es\n";
+  const char *define = "#define USE_NONUNIFORM_SAMPLING\n";
+
+  fragmentShaders[fragmentShaderCount++] = version;
+
+  // non-uniform sampling
+  if (bUseXform) {
+    fragmentShaders[fragmentShaderCount++] = define;
+  }
+
+  if (type == TONEMAP_INVERSE) {  // inverse tonemapping
+    fragmentShaders[fragmentShaderCount++] = rgba_inverse_tonemap_shader;
+  } else {  // forward tonemapping
+    fragmentShaders[fragmentShaderCount++] = forward_tonemap_shader;
+  }
+
+  tonemapper->programID =
+      engine_loadProgram(1, &fullscreen_vertex_shader, fragmentShaderCount, fragmentShaders);
+
+  // restore the caller context
+  engine_bind(caller_context);
+  engine_free_backup(caller_context);
+
+  return tonemapper;
+}
+
+//-----------------------------------------------------------------------------
+int Tonemapper::blit(const void *dst, const void *src, int srcFenceFd)
+//-----------------------------------------------------------------------------
+{
+  void* caller_context = engine_backup();
+  // make current
+  engine_bind(engineContext);
+
+  // create eglimages if required
+  EGLImageBuffer *dst_buffer = eglImageWrapper->wrap(dst);
+  EGLImageBuffer *src_buffer = eglImageWrapper->wrap(src);
+
+  // bind the program
+  engine_setProgram(programID);
+
+  engine_setData2f(3, tonemapScaleOffset);
+  bool bUseXform = (lutXformTexture != 0);
+  if( bUseXform )
+  {
+    engine_setData2f(4, lutXformScaleOffset);
+  }
+
+  // set destination
+  engine_setDestination(dst_buffer->getFramebuffer(), 0, 0, dst_buffer->getWidth(),
+                        dst_buffer->getHeight());
+  // set source
+  engine_setExternalInputBuffer(0, src_buffer->getTexture());
+  // set 3d lut
+  engine_set3DInputBuffer(1, tonemapTexture);
+  // set non-uniform xform
+  engine_set2DInputBuffer(2, lutXformTexture);
+
+  // perform
+  int fenceFD = engine_blit(srcFenceFd);
+
+  // restore the caller context
+  engine_bind(caller_context);
+  engine_free_backup(caller_context);
+
+
+  return fenceFD;
+}
diff --git a/sdm845/gpu_tonemapper/Tonemapper.h b/sdm845/gpu_tonemapper/Tonemapper.h
new file mode 100644
index 0000000..707cdfe
--- /dev/null
+++ b/sdm845/gpu_tonemapper/Tonemapper.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TONEMAPPER_TONEMAP_H__
+#define __TONEMAPPER_TONEMAP_H__
+
+#define TONEMAP_FORWARD 0
+#define TONEMAP_INVERSE 1
+
+#include "EGLImageWrapper.h"
+#include "engine.h"
+
+class Tonemapper {
+ private:
+  void* engineContext;
+  unsigned int tonemapTexture;
+  unsigned int lutXformTexture;
+  unsigned int programID;
+  float lutXformScaleOffset[2];
+  float tonemapScaleOffset[2];
+  EGLImageWrapper* eglImageWrapper;
+  Tonemapper();
+
+ public:
+  ~Tonemapper();
+  static Tonemapper *build(int type, void *colorMap, int colorMapSize, void *lutXform,
+                           int lutXformSize, bool isSecure);
+  int blit(const void *dst, const void *src, int srcFenceFd);
+};
+
+#endif  //__TONEMAPPER_TONEMAP_H__
diff --git a/sdm845/gpu_tonemapper/engine.h b/sdm845/gpu_tonemapper/engine.h
new file mode 100644
index 0000000..e0bf2aa
--- /dev/null
+++ b/sdm845/gpu_tonemapper/engine.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TONEMAPPER_ENGINE_H__
+#define __TONEMAPPER_ENGINE_H__
+
+void* engine_initialize(bool isSecure);
+void engine_bind(void*);
+void* engine_backup();
+void engine_free_backup(void*);
+void engine_shutdown(void*);
+
+unsigned int engine_loadProgram(int, const char **, int, const char **);
+void engine_setProgram(int);
+void engine_deleteProgram(unsigned int);
+
+unsigned int engine_load3DTexture(void *data, int sz, int format);
+unsigned int engine_load1DTexture(void *xform, int xformSize, int format);
+void engine_deleteInputBuffer(unsigned int);
+
+void engine_set2DInputBuffer(int binding, unsigned int textureID);
+void engine_set3DInputBuffer(int binding, unsigned int textureID);
+void engine_setExternalInputBuffer(int binding, unsigned int textureID);
+void engine_setDestination(int id, int x, int y, int w, int h);
+void engine_setData2f(int loc, float* data);
+
+int engine_blit(int);
+
+#endif  //__TONEMAPPER_ENGINE_H__
diff --git a/sdm845/gpu_tonemapper/forward_tonemap.inl b/sdm845/gpu_tonemapper/forward_tonemap.inl
new file mode 100644
index 0000000..0d89a9e
--- /dev/null
+++ b/sdm845/gpu_tonemapper/forward_tonemap.inl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const char* forward_tonemap_shader = ""
+    "#extension GL_OES_EGL_image_external_essl3 : require                       \n"
+    "precision highp float;                                                     \n"
+    "precision highp sampler2D;                                                 \n"
+    "layout(binding = 0) uniform samplerExternalOES externalTexture;            \n"
+    "layout(binding = 1) uniform sampler3D tonemapper;                          \n"
+    "layout(binding = 2) uniform sampler2D xform;                               \n"
+    "layout(location = 3) uniform vec2 tSO;                                     \n"
+    "#ifdef USE_NONUNIFORM_SAMPLING                                             \n"
+    "layout(location = 4) uniform vec2 xSO;                                     \n"
+    "#endif                                                                     \n"
+    "in vec2 uv;                                                                \n"
+    "out vec4 fs_color;                                                         \n"
+    "                                                                           \n"
+    "vec3 ScaleOffset(in vec3 samplePt, in vec2 so)                             \n"
+    "{                                                                          \n"
+    "   vec3 adjPt = so.x * samplePt + so.y;                                    \n"
+    "   return adjPt;                                                           \n"
+    "}                                                                          \n"
+    "                                                                           \n"
+    "void main()                                                                \n"
+    "{                                                                          \n"
+    "vec2 flipped = vec2(uv.x, 1.0f - uv.y);                                    \n"
+    "vec4 rgb = texture(externalTexture, flipped);                              \n"
+    "#ifdef USE_NONUNIFORM_SAMPLING                                             \n"
+    "vec3 adj = ScaleOffset(rgb.xyz, xSO);                                      \n"
+    "float r = texture(xform, vec2(adj.r, 0.5f)).r;                             \n"
+    "float g = texture(xform, vec2(adj.g, 0.5f)).g;                             \n"
+    "float b = texture(xform, vec2(adj.b, 0.5f)).b;                             \n"
+    "#else                                                                      \n"
+    "float r = rgb.r;                                                           \n"
+    "float g = rgb.g;                                                           \n"
+    "float b = rgb.b;                                                           \n"
+    "#endif                                                                     \n"
+    "fs_color.rgb = texture(tonemapper, ScaleOffset(vec3(r, g, b), tSO)).rgb;   \n"
+    "}                                                                          \n";
diff --git a/sdm845/gpu_tonemapper/fullscreen_vertex_shader.inl b/sdm845/gpu_tonemapper/fullscreen_vertex_shader.inl
new file mode 100644
index 0000000..9a70c2b
--- /dev/null
+++ b/sdm845/gpu_tonemapper/fullscreen_vertex_shader.inl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const char* fullscreen_vertex_shader = "                                      "
+"#version 300 es                                                            \n"
+"precision highp float;                                                     \n"
+"layout(location = 0) in vec2 iUV;                                          \n"
+"out vec2 uv;                                                               \n"
+"void main()                                                                \n"
+"{                                                                          \n"
+"    vec2 positions[3];                                                     \n"
+"    positions[0] = vec2(-1.0f, 3.0f);                                      \n"
+"    positions[1] = vec2(-1.0f, -1.0f);                                     \n"
+"    positions[2] = vec2(3.0f, -1.0f);                                      \n"
+"    vec2 uvs[3];                                                           \n"
+"    uvs[0] = vec2(0.0f, -1.0f);                                            \n"
+"    uvs[1] = vec2(0.0f, 1.0f);                                             \n"
+"    uvs[2] = vec2(2.0f, 1.0f);                                             \n"
+"    gl_Position = vec4(positions[gl_VertexID], -1.0f, 1.0f);               \n"
+"    uv = uvs[gl_VertexID];                                                 \n"
+"}                                                                          \n";
diff --git a/sdm845/gpu_tonemapper/glengine.cpp b/sdm845/gpu_tonemapper/glengine.cpp
new file mode 100644
index 0000000..6cfe15f
--- /dev/null
+++ b/sdm845/gpu_tonemapper/glengine.cpp
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "glengine.h"
+#include <utils/Log.h>
+#include "engine.h"
+
+void checkGlError(const char *, int);
+void checkEglError(const char *, int);
+
+class EngineContext {
+    public:
+    EGLDisplay eglDisplay;
+    EGLContext eglContext;
+    EGLSurface eglSurface;
+    EngineContext()
+    {
+        eglDisplay = EGL_NO_DISPLAY;
+        eglContext = EGL_NO_CONTEXT;
+        eglSurface = EGL_NO_SURFACE;
+    }
+};
+
+//-----------------------------------------------------------------------------
+// Make Current
+void engine_bind(void* context)
+//-----------------------------------------------------------------------------
+{
+  EngineContext* engineContext = (EngineContext*)(context);
+  EGL(eglMakeCurrent(engineContext->eglDisplay, engineContext->eglSurface, engineContext->eglSurface, engineContext->eglContext));
+}
+
+//-----------------------------------------------------------------------------
+// store the current context(caller)
+void* engine_backup()
+{
+  EngineContext* callerContext = new EngineContext();
+  // store the previous display/context
+  callerContext->eglDisplay = eglGetCurrentDisplay();
+  callerContext->eglContext = eglGetCurrentContext();
+  callerContext->eglSurface = eglGetCurrentSurface(EGL_DRAW);
+
+  return (void*)callerContext;
+}
+//-----------------------------------------------------------------------------
+// frees the backed up caller context
+void engine_free_backup(void* context)
+{
+  EngineContext* callerContext = (EngineContext*)(context);
+
+  delete callerContext;
+}
+
+//-----------------------------------------------------------------------------
+// initialize GL
+//
+void* engine_initialize(bool isSecure)
+//-----------------------------------------------------------------------------
+{
+  EngineContext* engineContext = new EngineContext();
+
+  // display
+  engineContext->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  EGL(eglBindAPI(EGL_OPENGL_ES_API));
+
+  // initialize
+  EGL(eglInitialize(engineContext->eglDisplay, 0, 0));
+
+  // config
+  EGLConfig eglConfig;
+  EGLint eglConfigAttribList[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+                                  EGL_RED_SIZE,     8,
+                                  EGL_GREEN_SIZE,   8,
+                                  EGL_BLUE_SIZE,    8,
+                                  EGL_ALPHA_SIZE,   8,
+                                  EGL_NONE};
+  int numConfig = 0;
+  EGL(eglChooseConfig(engineContext->eglDisplay, eglConfigAttribList, &eglConfig, 1, &numConfig));
+
+  // context
+  EGLint eglContextAttribList[] = {EGL_CONTEXT_CLIENT_VERSION, 3,
+                                   isSecure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+                                   isSecure ? EGL_TRUE : EGL_NONE,
+                                   EGL_NONE};
+  engineContext->eglContext = eglCreateContext(engineContext->eglDisplay, eglConfig, NULL, eglContextAttribList);
+
+  // surface
+  EGLint eglSurfaceAttribList[] = {EGL_WIDTH, 1,
+                                   EGL_HEIGHT, 1,
+                                   isSecure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+                                   isSecure ? EGL_TRUE : EGL_NONE,
+                                   EGL_NONE};
+  engineContext->eglSurface = eglCreatePbufferSurface(engineContext->eglDisplay, eglConfig, eglSurfaceAttribList);
+
+  eglMakeCurrent(engineContext->eglDisplay, engineContext->eglSurface, engineContext->eglSurface, engineContext->eglContext);
+
+  ALOGI("In %s context = %p", __FUNCTION__, (void *)(engineContext->eglContext));
+
+  return (void*)(engineContext);
+}
+
+//-----------------------------------------------------------------------------
+// Shutdown.
+void engine_shutdown(void* context)
+//-----------------------------------------------------------------------------
+{
+  EngineContext* engineContext = (EngineContext*)context;
+  EGL(eglMakeCurrent(engineContext->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+  EGL(eglDestroySurface(engineContext->eglDisplay, engineContext->eglSurface));
+  EGL(eglDestroyContext(engineContext->eglDisplay, engineContext->eglContext));
+  EGL(eglTerminate(engineContext->eglDisplay));
+  engineContext->eglDisplay = EGL_NO_DISPLAY;
+  engineContext->eglContext = EGL_NO_CONTEXT;
+  engineContext->eglSurface = EGL_NO_SURFACE;
+}
+
+//-----------------------------------------------------------------------------
+void engine_deleteInputBuffer(unsigned int id)
+//-----------------------------------------------------------------------------
+{
+  if (id != 0) {
+    GL(glDeleteTextures(1, &id));
+  }
+}
+
+//-----------------------------------------------------------------------------
+void engine_deleteProgram(unsigned int id)
+//-----------------------------------------------------------------------------
+{
+  if (id != 0) {
+    GL(glDeleteProgram(id));
+  }
+}
+
+//-----------------------------------------------------------------------------
+void engine_setData2f(int location, float* data)
+//-----------------------------------------------------------------------------
+{
+    GL(glUniform2f(location, data[0], data[1]));
+}
+
+//-----------------------------------------------------------------------------
+unsigned int engine_load3DTexture(void *colorMapData, int sz, int format)
+//-----------------------------------------------------------------------------
+{
+  GLuint texture = 0;
+  GL(glGenTextures(1, &texture));
+  GL(glBindTexture(GL_TEXTURE_3D, texture));
+  GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+  GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+  GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE));
+  GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+  GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+
+  GL(glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB10_A2, sz, sz, sz, 0, GL_RGBA,
+                  GL_UNSIGNED_INT_2_10_10_10_REV, colorMapData));
+
+  return texture;
+}
+//-----------------------------------------------------------------------------
+unsigned int engine_load1DTexture(void *data, int sz, int format)
+//-----------------------------------------------------------------------------
+{
+  GLuint texture = 0;
+  if ((data != 0) && (sz != 0)) {
+    GL(glGenTextures(1, &texture));
+    GL(glBindTexture(GL_TEXTURE_2D, texture));
+    GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+    GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+    GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+    GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+
+    GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, sz, 1, 0, GL_RGBA,
+                    GL_UNSIGNED_INT_2_10_10_10_REV, data));
+  }
+  return texture;
+}
+
+//-----------------------------------------------------------------------------
+void dumpShaderLog(int shader)
+//-----------------------------------------------------------------------------
+{
+  int success = 0;
+  GLchar infoLog[512];
+  GL(glGetShaderiv(shader, GL_COMPILE_STATUS, &success));
+  if (!success) {
+    glGetShaderInfoLog(shader, 512, NULL, infoLog);
+    ALOGI("Shader Failed to compile: %s\n", infoLog);
+  }
+}
+
+//-----------------------------------------------------------------------------
+GLuint engine_loadProgram(int vertexEntries, const char **vertex, int fragmentEntries,
+                          const char **fragment)
+//-----------------------------------------------------------------------------
+{
+  GLuint progId = glCreateProgram();
+
+  int vertId = glCreateShader(GL_VERTEX_SHADER);
+  int fragId = glCreateShader(GL_FRAGMENT_SHADER);
+
+  GL(glShaderSource(vertId, vertexEntries, vertex, 0));
+  GL(glCompileShader(vertId));
+  dumpShaderLog(vertId);
+
+  GL(glShaderSource(fragId, fragmentEntries, fragment, 0));
+  GL(glCompileShader(fragId));
+  dumpShaderLog(fragId);
+
+  GL(glAttachShader(progId, vertId));
+  GL(glAttachShader(progId, fragId));
+
+  GL(glLinkProgram(progId));
+
+  GL(glDetachShader(progId, vertId));
+  GL(glDetachShader(progId, fragId));
+
+  GL(glDeleteShader(vertId));
+  GL(glDeleteShader(fragId));
+
+  return progId;
+}
+
+//-----------------------------------------------------------------------------
+void WaitOnNativeFence(int fd)
+//-----------------------------------------------------------------------------
+{
+  if (fd != -1) {
+    EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fd, EGL_NONE};
+
+    EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+
+    if (sync == EGL_NO_SYNC_KHR) {
+      ALOGE("%s - Failed to Create sync from source fd", __FUNCTION__);
+    } else {
+      // the gpu will wait for this sync - not this cpu thread.
+      EGL(eglWaitSyncKHR(eglGetCurrentDisplay(), sync, 0));
+      EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
+    }
+  }
+}
+
+//-----------------------------------------------------------------------------
+int CreateNativeFence()
+//-----------------------------------------------------------------------------
+{
+  int fd = -1;
+
+  EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+  GL(glFlush());
+  if (sync == EGL_NO_SYNC_KHR) {
+    ALOGE("%s - Failed to Create Native Fence sync", __FUNCTION__);
+  } else {
+    fd = eglDupNativeFenceFDANDROID(eglGetCurrentDisplay(), sync);
+    if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+      ALOGE("%s - Failed to dup sync", __FUNCTION__);
+    }
+    EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
+  }
+
+  return fd;
+}
+
+//-----------------------------------------------------------------------------
+void engine_setDestination(int id, int x, int y, int w, int h)
+//-----------------------------------------------------------------------------
+{
+  GL(glBindFramebuffer(GL_FRAMEBUFFER, id));
+  GL(glViewport(x, y, w, h));
+}
+
+//-----------------------------------------------------------------------------
+void engine_setProgram(int id)
+//-----------------------------------------------------------------------------
+{
+  GL(glUseProgram(id));
+}
+
+//-----------------------------------------------------------------------------
+void engine_set2DInputBuffer(int binding, unsigned int id)
+//-----------------------------------------------------------------------------
+{
+  GL(glActiveTexture(GL_TEXTURE0 + binding));
+  GL(glBindTexture(GL_TEXTURE_2D, id));
+}
+
+//-----------------------------------------------------------------------------
+void engine_set3DInputBuffer(int binding, unsigned int id)
+//-----------------------------------------------------------------------------
+{
+  GL(glActiveTexture(GL_TEXTURE0 + binding));
+  GL(glBindTexture(GL_TEXTURE_3D, id));
+}
+
+//-----------------------------------------------------------------------------
+void engine_setExternalInputBuffer(int binding, unsigned int id)
+//-----------------------------------------------------------------------------
+{
+  GL(glActiveTexture(GL_TEXTURE0 + binding));
+  GL(glBindTexture(0x8D65, id));
+}
+
+//-----------------------------------------------------------------------------
+int engine_blit(int srcFenceFd)
+//-----------------------------------------------------------------------------
+{
+  int fd = -1;
+  WaitOnNativeFence(srcFenceFd);
+  float fullscreen_vertices[]{0.0f, 2.0f, 0.0f, 0.0f, 2.0f, 0.0f};
+  GL(glEnableVertexAttribArray(0));
+  GL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, fullscreen_vertices));
+  GL(glDrawArrays(GL_TRIANGLES, 0, 3));
+  fd = CreateNativeFence();
+  GL(glFlush());
+  return fd;
+}
+
+//-----------------------------------------------------------------------------
+void checkGlError(const char *file, int line)
+//-----------------------------------------------------------------------------
+{
+  for (GLint error = glGetError(); error; error = glGetError()) {
+    char *pError;
+    switch (error) {
+      case GL_NO_ERROR:
+        pError = (char *)"GL_NO_ERROR";
+        break;
+      case GL_INVALID_ENUM:
+        pError = (char *)"GL_INVALID_ENUM";
+        break;
+      case GL_INVALID_VALUE:
+        pError = (char *)"GL_INVALID_VALUE";
+        break;
+      case GL_INVALID_OPERATION:
+        pError = (char *)"GL_INVALID_OPERATION";
+        break;
+      case GL_OUT_OF_MEMORY:
+        pError = (char *)"GL_OUT_OF_MEMORY";
+        break;
+      case GL_INVALID_FRAMEBUFFER_OPERATION:
+        pError = (char *)"GL_INVALID_FRAMEBUFFER_OPERATION";
+        break;
+
+      default:
+        ALOGE("glError (0x%x) %s:%d\n", error, file, line);
+        return;
+    }
+
+    ALOGE("glError (%s) %s:%d\n", pError, file, line);
+    return;
+  }
+  return;
+}
+
+//-----------------------------------------------------------------------------
+void checkEglError(const char *file, int line)
+//-----------------------------------------------------------------------------
+{
+  for (int i = 0; i < 5; i++) {
+    const EGLint error = eglGetError();
+    if (error == EGL_SUCCESS) {
+      break;
+    }
+
+    char *pError;
+    switch (error) {
+      case EGL_SUCCESS:
+        pError = (char *)"EGL_SUCCESS";
+        break;
+      case EGL_NOT_INITIALIZED:
+        pError = (char *)"EGL_NOT_INITIALIZED";
+        break;
+      case EGL_BAD_ACCESS:
+        pError = (char *)"EGL_BAD_ACCESS";
+        break;
+      case EGL_BAD_ALLOC:
+        pError = (char *)"EGL_BAD_ALLOC";
+        break;
+      case EGL_BAD_ATTRIBUTE:
+        pError = (char *)"EGL_BAD_ATTRIBUTE";
+        break;
+      case EGL_BAD_CONTEXT:
+        pError = (char *)"EGL_BAD_CONTEXT";
+        break;
+      case EGL_BAD_CONFIG:
+        pError = (char *)"EGL_BAD_CONFIG";
+        break;
+      case EGL_BAD_CURRENT_SURFACE:
+        pError = (char *)"EGL_BAD_CURRENT_SURFACE";
+        break;
+      case EGL_BAD_DISPLAY:
+        pError = (char *)"EGL_BAD_DISPLAY";
+        break;
+      case EGL_BAD_SURFACE:
+        pError = (char *)"EGL_BAD_SURFACE";
+        break;
+      case EGL_BAD_MATCH:
+        pError = (char *)"EGL_BAD_MATCH";
+        break;
+      case EGL_BAD_PARAMETER:
+        pError = (char *)"EGL_BAD_PARAMETER";
+        break;
+      case EGL_BAD_NATIVE_PIXMAP:
+        pError = (char *)"EGL_BAD_NATIVE_PIXMAP";
+        break;
+      case EGL_BAD_NATIVE_WINDOW:
+        pError = (char *)"EGL_BAD_NATIVE_WINDOW";
+        break;
+      case EGL_CONTEXT_LOST:
+        pError = (char *)"EGL_CONTEXT_LOST";
+        break;
+      default:
+        ALOGE("eglError (0x%x) %s:%d\n", error, file, line);
+        return;
+    }
+    ALOGE("eglError (%s) %s:%d\n", pError, file, line);
+    return;
+  }
+  return;
+}
diff --git a/sdm845/gpu_tonemapper/glengine.h b/sdm845/gpu_tonemapper/glengine.h
new file mode 100644
index 0000000..f6aeec8
--- /dev/null
+++ b/sdm845/gpu_tonemapper/glengine.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TONEMAPPER_GLENGINE_H__
+#define __TONEMAPPER_GLENGINE_H__
+#include <EGL/egl.h>
+#define EGL_EGLEXT_PROTOTYPES
+#include <EGL/eglext.h>
+#include <GLES3/gl31.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GLES2/gl2ext.h>
+#include <GLES3/gl3ext.h>
+
+#if defined(CHECK_GL_ERRORS)
+#define GL(func) func;
+#define EGL(func) func;
+#else
+#define GL(func) \
+  func;          \
+  checkGlError(__FILE__, __LINE__);
+#define EGL(func) \
+  func;           \
+  checkEglError(__FILE__, __LINE__);
+#endif
+
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
+
+void checkGlError(const char *file, int line);
+void checkEglError(const char *file, int line);
+
+#endif  //__TONEMAPPER_GLENGINE_H__
diff --git a/sdm845/gpu_tonemapper/rgba_inverse_tonemap.inl b/sdm845/gpu_tonemapper/rgba_inverse_tonemap.inl
new file mode 100644
index 0000000..2865fbe
--- /dev/null
+++ b/sdm845/gpu_tonemapper/rgba_inverse_tonemap.inl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const char* rgba_inverse_tonemap_shader = ""
+    "#extension GL_OES_EGL_image_external_essl3 : require                                               \n"
+    "precision highp float;                                                                             \n"
+    "precision highp sampler2D;                                                                         \n"
+    "layout(binding = 0) uniform samplerExternalOES externalTexture;                                    \n"
+    "layout(binding = 1) uniform sampler3D tonemapper;                                                  \n"
+    "layout(binding = 2) uniform sampler2D xform;                                                       \n"
+    "layout(location = 3) uniform vec2 tSO;                                                             \n"
+    "#if defined(USE_NONUNIFORM_SAMPLING)                                                               \n"
+    "layout(location = 4) uniform vec2 xSO;                                                             \n"
+    "#endif                                                                                             \n"
+    "in vec2 uv;                                                                                        \n"
+    "out vec4 fs_color;                                                                                 \n"
+    "                                                                                                   \n"
+    "vec3 ScaleOffset(in vec3 samplePt, in vec2 so)                                                     \n"
+    "{                                                                                                  \n"
+    "   vec3 adjPt = so.x * samplePt + so.y;                                                            \n"
+    "   return adjPt;                                                                                   \n"
+    "}                                                                                                  \n"
+    "                                                                                                   \n"
+    "void main()                                                                                        \n"
+    "{                                                                                                  \n"
+    "vec2 flipped = vec2(uv.x, 1.0f - uv.y);                                                            \n"
+    "vec4 rgb_premulalpha = texture(externalTexture, flipped);                                          \n"
+    "fs_color = rgb_premulalpha;                                                                        \n"
+    "if( rgb_premulalpha.a > 0.0 ) {                                                                    \n"
+    "vec3 rgb = rgb_premulalpha.rgb/rgb_premulalpha.a;                                                  \n"
+    "#if defined(USE_NONUNIFORM_SAMPLING)                                                               \n"
+    "vec3 adj = ScaleOffset(rgb.xyz, xSO);                                                              \n"
+    "float r = texture(xform, vec2(adj.r, 0.5f)).r;                                                     \n"
+    "float g = texture(xform, vec2(adj.g, 0.5f)).g;                                                     \n"
+    "float b = texture(xform, vec2(adj.b, 0.5f)).b;                                                     \n"
+    "#else                                                                                              \n"
+    "float r = rgb.r;                                                                                   \n"
+    "float g = rgb.g;                                                                                   \n"
+    "float b = rgb.b;                                                                                   \n"
+    "#endif                                                                                             \n"
+    "fs_color.rgb = texture(tonemapper, ScaleOffset(vec3(r, g, b), tSO)).rgb * rgb_premulalpha.a;       \n"
+    "fs_color.a = rgb_premulalpha.a;                                                                    \n"
+    "}                                                                                                  \n"
+    "}                                                                                                  \n";
diff --git a/sdm845/hdmi_cec/Android.mk b/sdm845/hdmi_cec/Android.mk
new file mode 100644
index 0000000..a333654
--- /dev/null
+++ b/sdm845/hdmi_cec/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := hdmi_cec.$(TARGET_BOARD_PLATFORM)
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_RELATIVE_PATH    := hw
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes)
+LOCAL_HEADER_LIBRARIES        := display_headers
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libqservice libbinder libqdutils
+
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdhdmi_cec\" -Wno-sign-conversion
+LOCAL_CLANG                   := true
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_SRC_FILES               := qhdmi_cec.cpp \
+                                 QHDMIClient.cpp
+include $(BUILD_SHARED_LIBRARY)
diff --git a/sdm845/hdmi_cec/QHDMIClient.cpp b/sdm845/hdmi_cec/QHDMIClient.cpp
new file mode 100644
index 0000000..2b2b1e6
--- /dev/null
+++ b/sdm845/hdmi_cec/QHDMIClient.cpp
@@ -0,0 +1,66 @@
+/*
+* 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.
+*/
+
+#define DEBUG 0
+#include <QServiceUtils.h>
+#include "QHDMIClient.h"
+
+using namespace android;
+using namespace qhdmicec;
+using namespace qService;
+
+namespace qClient {
+
+void QHDMIClient::binderDied(const wp<IBinder>& who __unused)
+{
+    ALOGW("%s: Display QService died", __FUNCTION__);
+}
+
+void QHDMIClient::onHdmiHotplug(int connected)
+{
+    ALOGD("%s: HDMI connected event connected: %d", __FUNCTION__, connected);
+    cec_hdmi_hotplug(mCtx, connected);
+}
+
+void QHDMIClient::onCECMessageRecieved(char *msg, ssize_t len)
+{
+    ALOGD_IF(DEBUG, "%s: CEC message received len: %zd", __FUNCTION__, len);
+    cec_receive_message(mCtx, msg, len);
+}
+
+void QHDMIClient::registerClient(sp<QHDMIClient>& client)
+{
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16("display.qservice"));
+    binder->linkToDeath(client);
+    mQService = interface_cast<IQService>(binder);
+    mQService->connect(interface_cast<IQHDMIClient>(client));
+}
+
+};
diff --git a/sdm845/hdmi_cec/QHDMIClient.h b/sdm845/hdmi_cec/QHDMIClient.h
new file mode 100644
index 0000000..9e54f2f
--- /dev/null
+++ b/sdm845/hdmi_cec/QHDMIClient.h
@@ -0,0 +1,57 @@
+/*
+* 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 "IQHDMIClient.h"
+#include "qhdmi_cec.h"
+#include <IQService.h>
+
+namespace qClient {
+
+class QHDMIClient: public android::IBinder::DeathRecipient,
+    public BnQHDMIClient
+{
+public:
+    QHDMIClient() {}
+
+    virtual void binderDied(const android::wp<android::IBinder>& who);
+
+    virtual void onHdmiHotplug(int connected);
+
+    virtual void onCECMessageRecieved(char *msg, ssize_t len);
+
+    void setCECContext(qhdmicec::cec_context_t* ctx) { mCtx = ctx; }
+
+    void registerClient(android::sp<QHDMIClient>& client);
+
+private:
+    qhdmicec::cec_context_t* mCtx;
+    android::sp<qService::IQService> mQService;
+
+};
+};
diff --git a/sdm845/hdmi_cec/qhdmi_cec.cpp b/sdm845/hdmi_cec/qhdmi_cec.cpp
new file mode 100644
index 0000000..0923d92
--- /dev/null
+++ b/sdm845/hdmi_cec/qhdmi_cec.cpp
@@ -0,0 +1,520 @@
+/*
+* Copyright (c) 2014, 2016-2017, 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 DEBUG 0
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+#include <cstdlib>
+#include <cutils/log.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <hardware/hdmi_cec.h>
+#include <utils/Trace.h>
+#include "qhdmi_cec.h"
+#include "QHDMIClient.h"
+
+namespace qhdmicec {
+
+const int NUM_HDMI_PORTS = 1;
+const int MAX_SYSFS_DATA = 128;
+const int MAX_CEC_FRAME_SIZE = 20;
+const int MAX_SEND_MESSAGE_RETRIES = 1;
+
+enum {
+    LOGICAL_ADDRESS_SET   =  1,
+    LOGICAL_ADDRESS_UNSET = -1,
+};
+
+// Offsets of members of struct hdmi_cec_msg
+// drivers/video/msm/mdss/mdss_hdmi_cec.c
+// XXX: Get this from a driver header
+enum {
+    CEC_OFFSET_SENDER_ID,
+    CEC_OFFSET_RECEIVER_ID,
+    CEC_OFFSET_OPCODE,
+    CEC_OFFSET_OPERAND,
+    CEC_OFFSET_FRAME_LENGTH = 17,
+    CEC_OFFSET_RETRANSMIT,
+};
+
+//Forward declarations
+static void cec_close_context(cec_context_t* ctx __unused);
+static int cec_enable(cec_context_t *ctx, int enable);
+static int cec_is_connected(const struct hdmi_cec_device* dev, int port_id);
+
+static ssize_t read_node(const char *path, char *data)
+{
+    ssize_t err = 0;
+    FILE *fp = NULL;
+    err = access(path, R_OK);
+    if (!err) {
+        fp = fopen(path, "r");
+        if (fp) {
+            err = fread(data, sizeof(char), MAX_SYSFS_DATA ,fp);
+            fclose(fp);
+        }
+    }
+    return err;
+}
+
+static ssize_t write_node(const char *path, const char *data, size_t len)
+{
+    ssize_t err = 0;
+    int fd = -1;
+    err = access(path, W_OK);
+    if (!err) {
+        fd = open(path, O_WRONLY);
+        errno = 0;
+        err = write(fd, data, len);
+        if (err < 0) {
+            err = -errno;
+        }
+        close(fd);
+    } else {
+        ALOGE("%s: Failed to access path: %s error: %s",
+                __FUNCTION__, path, strerror(errno));
+        err = -errno;
+    }
+    return err;
+}
+
+// Helper function to write integer values to the full sysfs path
+static ssize_t write_int_to_node(cec_context_t *ctx,
+        const char *path_postfix,
+        const int value)
+{
+    char sysfs_full_path[MAX_PATH_LENGTH];
+    char sysfs_data[MAX_SYSFS_DATA];
+    snprintf(sysfs_data, sizeof(sysfs_data), "%d",value);
+    snprintf(sysfs_full_path,sizeof(sysfs_full_path), "%s/%s",
+            ctx->fb_sysfs_path, path_postfix);
+    ssize_t err = write_node(sysfs_full_path, sysfs_data, strlen(sysfs_data));
+    return err;
+}
+
+static void hex_to_string(const char *msg, ssize_t len, char *str)
+{
+    //Functions assumes sufficient memory in str
+    char *ptr = str;
+    for(int i=0; i < len ; i++) {
+        ptr += snprintf(ptr, 3,  "%02X", msg[i]);
+        // Overwrite null termination of snprintf in all except the last byte
+        if (i < len - 1)
+            *ptr = ':';
+        ptr++;
+    }
+}
+
+static ssize_t cec_get_fb_node_number(cec_context_t *ctx)
+{
+    //XXX: Do this from a common utility library across the display HALs
+    const int MAX_FB_DEVICES = 2;
+    ssize_t len = 0;
+    char fb_type_path[MAX_PATH_LENGTH];
+    char fb_type[MAX_SYSFS_DATA];
+    const char *dtv_panel_str = "dtv panel";
+
+    for(int num = 0; num < MAX_FB_DEVICES; num++) {
+        snprintf(fb_type_path, sizeof(fb_type_path),"%s%d/msm_fb_type",
+                SYSFS_BASE,num);
+        ALOGD_IF(DEBUG, "%s: num: %d fb_type_path: %s", __FUNCTION__, num, fb_type_path);
+        len = read_node(fb_type_path, fb_type);
+        ALOGD_IF(DEBUG, "%s: fb_type:%s", __FUNCTION__, fb_type);
+        if(len > 0 && (strncmp(fb_type, dtv_panel_str, strlen(dtv_panel_str)) == 0)){
+            ALOGD_IF(DEBUG, "%s: Found DTV panel at fb%d", __FUNCTION__, num);
+            ctx->fb_num = num;
+            snprintf(ctx->fb_sysfs_path, sizeof(ctx->fb_sysfs_path),
+                    "%s%d", SYSFS_BASE, num);
+            break;
+        }
+    }
+    if (len < 0)
+        return len;
+    else
+        return 0;
+}
+
+static int cec_add_logical_address(const struct hdmi_cec_device* dev,
+        cec_logical_address_t addr)
+{
+    if (addr <  CEC_ADDR_TV || addr > CEC_ADDR_BROADCAST) {
+        ALOGE("%s: Received invalid address: %d ", __FUNCTION__, addr);
+        return -EINVAL;
+    }
+    cec_context_t* ctx = (cec_context_t*)(dev);
+    ctx->logical_address[addr] = LOGICAL_ADDRESS_SET;
+
+    //XXX: We can get multiple logical addresses here but we can only send one
+    //to the driver. Store locally for now
+    ssize_t err = write_int_to_node(ctx, "cec/logical_addr", addr);
+    ALOGI("%s: Allocated logical address: %d ", __FUNCTION__, addr);
+    return (int) err;
+}
+
+static void cec_clear_logical_address(const struct hdmi_cec_device* dev)
+{
+    cec_context_t* ctx = (cec_context_t*)(dev);
+    memset(ctx->logical_address, LOGICAL_ADDRESS_UNSET,
+            sizeof(ctx->logical_address));
+    //XXX: Find logical_addr that needs to be reset
+    write_int_to_node(ctx, "cec/logical_addr", 15);
+    ALOGD_IF(DEBUG, "%s: Cleared logical addresses", __FUNCTION__);
+}
+
+static int cec_get_physical_address(const struct hdmi_cec_device* dev,
+        uint16_t* addr)
+{
+    cec_context_t* ctx = (cec_context_t*)(dev);
+    char pa_path[MAX_PATH_LENGTH];
+    char pa_data[MAX_SYSFS_DATA];
+    snprintf (pa_path, sizeof(pa_path),"%s/pa",
+            ctx->fb_sysfs_path);
+    int err = (int) read_node(pa_path, pa_data);
+    *addr = (uint16_t) atoi(pa_data);
+    ALOGD_IF(DEBUG, "%s: Physical Address: 0x%x", __FUNCTION__, *addr);
+    if (err < 0)
+        return err;
+    else
+        return 0;
+}
+
+static int cec_send_message(const struct hdmi_cec_device* dev,
+        const cec_message_t* msg)
+{
+    ATRACE_CALL();
+    if(cec_is_connected(dev, 0) <= 0)
+        return HDMI_RESULT_FAIL;
+
+    cec_context_t* ctx = (cec_context_t*)(dev);
+    ALOGD_IF(DEBUG, "%s: initiator: %d destination: %d length: %u",
+            __FUNCTION__, msg->initiator, msg->destination,
+            (uint32_t) msg->length);
+
+    // Dump message received from framework
+    char dump[128];
+    if(msg->length > 0) {
+        hex_to_string((char*)msg->body, msg->length, dump);
+        ALOGD_IF(DEBUG, "%s: message from framework: %s", __FUNCTION__, dump);
+    }
+
+    char write_msg_path[MAX_PATH_LENGTH];
+    char write_msg[MAX_CEC_FRAME_SIZE];
+    memset(write_msg, 0, sizeof(write_msg));
+    // See definition of struct hdmi_cec_msg in driver code
+    // drivers/video/msm/mdss/mdss_hdmi_cec.c
+    // Write header block
+    // XXX: Include this from header in kernel
+    write_msg[CEC_OFFSET_SENDER_ID] = msg->initiator;
+    write_msg[CEC_OFFSET_RECEIVER_ID] = msg->destination;
+    //Kernel splits opcode/operand, but Android sends it in one byte array
+    write_msg[CEC_OFFSET_OPCODE] = msg->body[0];
+    if(msg->length > 1) {
+        memcpy(&write_msg[CEC_OFFSET_OPERAND], &msg->body[1],
+                sizeof(char)*(msg->length - 1));
+    }
+    //msg length + initiator + destination
+    write_msg[CEC_OFFSET_FRAME_LENGTH] = (unsigned char) (msg->length + 1);
+    hex_to_string(write_msg, sizeof(write_msg), dump);
+    ALOGD_IF(DEBUG, "%s: message to driver: %s", __FUNCTION__, dump);
+    snprintf(write_msg_path, sizeof(write_msg_path), "%s/cec/wr_msg",
+            ctx->fb_sysfs_path);
+    int retry_count = 0;
+    ssize_t err = 0;
+    //HAL spec requires us to retry at least once.
+    while (true) {
+        err = write_node(write_msg_path, write_msg, sizeof(write_msg));
+        retry_count++;
+        if (err == -EAGAIN && retry_count <= MAX_SEND_MESSAGE_RETRIES) {
+            ALOGE("%s: CEC line busy, retrying", __FUNCTION__);
+        } else {
+            break;
+        }
+    }
+
+    if (err < 0) {
+       if (err == -ENXIO) {
+           ALOGI("%s: No device exists with the destination address",
+                   __FUNCTION__);
+           return HDMI_RESULT_NACK;
+       } else if (err == -EAGAIN) {
+            ALOGE("%s: CEC line is busy, max retry count exceeded",
+                    __FUNCTION__);
+            return HDMI_RESULT_BUSY;
+        } else {
+            return HDMI_RESULT_FAIL;
+            ALOGE("%s: Failed to send CEC message err: %zd - %s",
+                    __FUNCTION__, err, strerror(int(-err)));
+        }
+    } else {
+        ALOGD_IF(DEBUG, "%s: Sent CEC message - %zd bytes written",
+                __FUNCTION__, err);
+        return HDMI_RESULT_SUCCESS;
+    }
+}
+
+void cec_receive_message(cec_context_t *ctx, char *msg, ssize_t len)
+{
+    if(!ctx->system_control)
+        return;
+
+    char dump[128];
+    if(len > 0) {
+        hex_to_string(msg, len, dump);
+        ALOGD_IF(DEBUG, "%s: Message from driver: %s", __FUNCTION__, dump);
+    }
+
+    hdmi_event_t event;
+    event.type = HDMI_EVENT_CEC_MESSAGE;
+    event.dev = (hdmi_cec_device *) ctx;
+    // Remove initiator/destination from this calculation
+    event.cec.length = msg[CEC_OFFSET_FRAME_LENGTH] - 1;
+    event.cec.initiator = (cec_logical_address_t) msg[CEC_OFFSET_SENDER_ID];
+    event.cec.destination = (cec_logical_address_t) msg[CEC_OFFSET_RECEIVER_ID];
+    //Copy opcode and operand
+    size_t copy_size = event.cec.length > sizeof(event.cec.body) ?
+                       sizeof(event.cec.body) : event.cec.length;
+    memcpy(event.cec.body, &msg[CEC_OFFSET_OPCODE],copy_size);
+    hex_to_string((char *) event.cec.body, copy_size, dump);
+    ALOGD_IF(DEBUG, "%s: Message to framework: %s", __FUNCTION__, dump);
+    ctx->callback.callback_func(&event, ctx->callback.callback_arg);
+}
+
+void cec_hdmi_hotplug(cec_context_t *ctx, int connected)
+{
+    //Ignore unplug events when system control is disabled
+    if(!ctx->system_control && connected == 0)
+        return;
+    hdmi_event_t event;
+    event.type = HDMI_EVENT_HOT_PLUG;
+    event.dev = (hdmi_cec_device *) ctx;
+    event.hotplug.connected = connected ? HDMI_CONNECTED : HDMI_NOT_CONNECTED;
+    ctx->callback.callback_func(&event, ctx->callback.callback_arg);
+}
+
+static void cec_register_event_callback(const struct hdmi_cec_device* dev,
+            event_callback_t callback, void* arg)
+{
+    ALOGD_IF(DEBUG, "%s: Registering callback", __FUNCTION__);
+    cec_context_t* ctx = (cec_context_t*)(dev);
+    ctx->callback.callback_func = callback;
+    ctx->callback.callback_arg = arg;
+}
+
+static void cec_get_version(const struct hdmi_cec_device* dev, int* version)
+{
+    cec_context_t* ctx = (cec_context_t*)(dev);
+    *version = ctx->version;
+    ALOGD_IF(DEBUG, "%s: version: %d", __FUNCTION__, *version);
+}
+
+static void cec_get_vendor_id(const struct hdmi_cec_device* dev,
+        uint32_t* vendor_id)
+{
+    cec_context_t* ctx = (cec_context_t*)(dev);
+    *vendor_id = ctx->vendor_id;
+    ALOGD_IF(DEBUG, "%s: vendor id: %u", __FUNCTION__, *vendor_id);
+}
+
+static void cec_get_port_info(const struct hdmi_cec_device* dev,
+            struct hdmi_port_info* list[], int* total)
+{
+    ALOGD_IF(DEBUG, "%s: Get port info", __FUNCTION__);
+    cec_context_t* ctx = (cec_context_t*)(dev);
+    *total = NUM_HDMI_PORTS;
+    *list = ctx->port_info;
+}
+
+static void cec_set_option(const struct hdmi_cec_device* dev, int flag,
+        int value)
+{
+    cec_context_t* ctx = (cec_context_t*)(dev);
+    switch (flag) {
+        case HDMI_OPTION_WAKEUP:
+            ALOGD_IF(DEBUG, "%s: Wakeup: value: %d", __FUNCTION__, value);
+            //XXX
+            break;
+        case HDMI_OPTION_ENABLE_CEC:
+            ALOGD_IF(DEBUG, "%s: Enable CEC: value: %d", __FUNCTION__, value);
+            cec_enable(ctx, value? 1 : 0);
+            break;
+        case HDMI_OPTION_SYSTEM_CEC_CONTROL:
+            ALOGD_IF(DEBUG, "%s: system_control: value: %d",
+                    __FUNCTION__, value);
+            ctx->system_control = !!value;
+            break;
+    }
+}
+
+static void cec_set_audio_return_channel(const struct hdmi_cec_device* dev,
+        int port, int flag)
+{
+    cec_context_t* ctx = (cec_context_t*)(dev);
+    ctx->arc_enabled = flag ? true : false;
+    ALOGD_IF(DEBUG, "%s: ARC flag: %d port: %d", __FUNCTION__, flag, port);
+}
+
+static int cec_is_connected(const struct hdmi_cec_device* dev, int port_id)
+{
+    // Ignore port_id since we have only one port
+    int connected = 0;
+    cec_context_t* ctx = (cec_context_t*)(dev);
+    char connected_path[MAX_PATH_LENGTH];
+    char connected_data[MAX_SYSFS_DATA];
+    snprintf (connected_path, sizeof(connected_path),"%s/connected",
+            ctx->fb_sysfs_path);
+    ssize_t err = read_node(connected_path, connected_data);
+    connected = atoi(connected_data);
+
+    ALOGD_IF(DEBUG, "%s: HDMI at port %d is - %s", __FUNCTION__, port_id,
+            connected ? "connected":"disconnected");
+    if (err < 0)
+        return (int) err;
+    else
+        return connected;
+}
+
+static int cec_device_close(struct hw_device_t *dev)
+{
+    ALOGD_IF(DEBUG, "%s: Close CEC HAL ", __FUNCTION__);
+    if (!dev) {
+        ALOGE("%s: NULL device pointer", __FUNCTION__);
+        return -EINVAL;
+    }
+    cec_context_t* ctx = (cec_context_t*)(dev);
+    cec_close_context(ctx);
+    free(dev);
+    return 0;
+}
+
+static int cec_enable(cec_context_t *ctx, int enable)
+{
+    ssize_t err;
+    // Enable CEC
+    int value = enable ? 0x3 : 0x0;
+    err = write_int_to_node(ctx, "cec/enable", value);
+    if(err < 0) {
+        ALOGE("%s: Failed to toggle CEC: enable: %d",
+                __FUNCTION__, enable);
+        return (int) err;
+    }
+    ctx->enabled = enable;
+    return 0;
+}
+
+static void cec_init_context(cec_context_t *ctx)
+{
+    ALOGD_IF(DEBUG, "%s: Initializing context", __FUNCTION__);
+    cec_get_fb_node_number(ctx);
+
+    //Initialize ports - We support only one output port
+    ctx->port_info = new hdmi_port_info[NUM_HDMI_PORTS];
+    ctx->port_info[0].type = HDMI_OUTPUT;
+    ctx->port_info[0].port_id = 1;
+    ctx->port_info[0].cec_supported = 1;
+    //XXX: Enable ARC if supported
+    ctx->port_info[0].arc_supported = 0;
+    cec_get_physical_address((hdmi_cec_device *) ctx,
+            &ctx->port_info[0].physical_address );
+
+    ctx->version = 0x4;
+    ctx->vendor_id = 0xA47733;
+    cec_clear_logical_address((hdmi_cec_device_t*)ctx);
+
+    //Set up listener for HDMI events
+    ctx->disp_client = new qClient::QHDMIClient();
+    ctx->disp_client->setCECContext(ctx);
+    ctx->disp_client->registerClient(ctx->disp_client);
+
+    //Enable CEC - framework expects it to be enabled by default
+    cec_enable(ctx, true);
+
+    ALOGD("%s: CEC enabled", __FUNCTION__);
+}
+
+static void cec_close_context(cec_context_t* ctx __unused)
+{
+    ALOGD("%s: Closing context", __FUNCTION__);
+}
+
+static int cec_device_open(const struct hw_module_t* module,
+        const char* name,
+        struct hw_device_t** device)
+{
+    ALOGD_IF(DEBUG, "%s: name: %s", __FUNCTION__, name);
+    int status = -EINVAL;
+    if (!strcmp(name, HDMI_CEC_HARDWARE_INTERFACE )) {
+        struct cec_context_t *dev;
+        dev = (cec_context_t *) calloc (1, sizeof(*dev));
+        if (dev) {
+            cec_init_context(dev);
+
+            //Setup CEC methods
+            dev->device.common.tag       = HARDWARE_DEVICE_TAG;
+            dev->device.common.version   = HDMI_CEC_DEVICE_API_VERSION_1_0;
+            dev->device.common.module    = const_cast<hw_module_t* >(module);
+            dev->device.common.close     = cec_device_close;
+            dev->device.add_logical_address = cec_add_logical_address;
+            dev->device.clear_logical_address = cec_clear_logical_address;
+            dev->device.get_physical_address = cec_get_physical_address;
+            dev->device.send_message = cec_send_message;
+            dev->device.register_event_callback = cec_register_event_callback;
+            dev->device.get_version = cec_get_version;
+            dev->device.get_vendor_id = cec_get_vendor_id;
+            dev->device.get_port_info = cec_get_port_info;
+            dev->device.set_option = cec_set_option;
+            dev->device.set_audio_return_channel = cec_set_audio_return_channel;
+            dev->device.is_connected = cec_is_connected;
+
+            *device = &dev->device.common;
+            status = 0;
+        } else {
+            status = -EINVAL;
+        }
+    }
+    return status;
+}
+}; //namespace qhdmicec
+
+// Standard HAL module, should be outside qhdmicec namespace
+static struct hw_module_methods_t cec_module_methods = {
+        .open = qhdmicec::cec_device_open
+};
+
+hdmi_module_t HAL_MODULE_INFO_SYM = {
+    .common = {
+        .tag = HARDWARE_MODULE_TAG,
+        .version_major = 1,
+        .version_minor = 0,
+        .id = HDMI_CEC_HARDWARE_MODULE_ID,
+        .name = "QTI HDMI CEC module",
+        .author = "The Linux Foundation",
+        .methods = &cec_module_methods,
+    }
+};
+
+
diff --git a/sdm845/hdmi_cec/qhdmi_cec.h b/sdm845/hdmi_cec/qhdmi_cec.h
new file mode 100644
index 0000000..aa97620
--- /dev/null
+++ b/sdm845/hdmi_cec/qhdmi_cec.h
@@ -0,0 +1,74 @@
+/*
+* 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 QHDMI_CEC_H
+#define QHDMI_CEC_H
+
+#include <hardware/hdmi_cec.h>
+#include <utils/RefBase.h>
+
+namespace qClient {
+    class QHDMIClient;
+};
+
+namespace qhdmicec {
+
+#define SYSFS_BASE  "/sys/class/graphics/fb"
+#define MAX_PATH_LENGTH  128
+
+struct cec_callback_t {
+    // Function in HDMI service to call back on CEC messages
+    event_callback_t callback_func;
+    // This stores the object to pass back to the framework
+    void* callback_arg;
+
+};
+
+struct cec_context_t {
+    hdmi_cec_device_t device;    // Device for HW module
+    cec_callback_t callback;     // Struct storing callback object
+    bool enabled;
+    bool arc_enabled;
+    bool system_control;         // If true, HAL/driver handle CEC messages
+    int fb_num;                  // Framebuffer node for HDMI
+    char fb_sysfs_path[MAX_PATH_LENGTH];
+    hdmi_port_info *port_info;   // HDMI port info
+
+    // Logical address is stored in an array, the index of the array is the
+    // logical address and the value in the index shows whether it is set or not
+    int logical_address[CEC_ADDR_BROADCAST];
+    int version;
+    uint32_t vendor_id;
+    android::sp<qClient::QHDMIClient> disp_client;
+};
+
+void cec_receive_message(cec_context_t *ctx, char *msg, ssize_t len);
+void cec_hdmi_hotplug(cec_context_t *ctx, int connected);
+
+}; //namespace
+#endif /* end of include guard: QHDMI_CEC_H */
diff --git a/sdm845/include/Android.mk b/sdm845/include/Android.mk
new file mode 100644
index 0000000..ec07dde
--- /dev/null
+++ b/sdm845/include/Android.mk
@@ -0,0 +1,26 @@
+LOCAL_PATH:= $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
+LOCAL_COPY_HEADERS            := color_metadata.h
+
+include $(BUILD_COPY_HEADERS)
+
+include $(CLEAR_VARS)
+#TODO move all exported headers to this directory
+LOCAL_MODULE := display_headers
+LOCAL_EXPORT_C_INCLUDE_DIRS   := $(LOCAL_PATH) \
+                                 $(display_top)/libcopybit \
+                                 $(display_top)/libdrmutils \
+                                 $(display_top)/libqdutils \
+                                 $(display_top)/libqservice \
+                                 $(display_top)/gpu_tonemapper \
+                                 $(display_top)/sdm/include
+
+ifeq ($(TARGET_USES_GRALLOC1), true)
+    LOCAL_EXPORT_C_INCLUDE_DIRS += $(display_top)/libgralloc1
+else
+    LOCAL_EXPORT_C_INCLUDE_DIRS += $(display_top)/libgralloc
+endif
+include $(BUILD_HEADER_LIBRARY)
diff --git a/sdm845/include/color_metadata.h b/sdm845/include/color_metadata.h
new file mode 100644
index 0000000..aff6fc9
--- /dev/null
+++ b/sdm845/include/color_metadata.h
@@ -0,0 +1,189 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __COLOR_METADATA_H__
+#define __COLOR_METADATA_H__
+
+#ifdef __cplusplus
+extern "C" {
+#else
+#include <stdbool.h>
+#endif
+
+typedef enum ColorRange {
+  Range_Limited = 0,
+  Range_Full    = 1,
+  Range_Max     = 0xff,
+} ColorRange;
+
+// The following values matches the HEVC spec
+typedef enum ColorPrimaries {
+  // Unused = 0;
+  ColorPrimaries_BT709_5     = 1,  // ITU-R BT.709-5 or equivalent
+  /* Unspecified = 2, Reserved = 3*/
+  ColorPrimaries_BT470_6M    = 4,  // ITU-R BT.470-6 System M or equivalent
+  ColorPrimaries_BT601_6_625 = 5,  // ITU-R BT.601-6 625 or equivalent
+  ColorPrimaries_BT601_6_525 = 6,  // ITU-R BT.601-6 525 or equivalent
+  ColorPrimaries_SMPTE_240M  = 7,  // SMPTE_240M
+  ColorPrimaries_GenericFilm = 8,  // Generic Film
+  ColorPrimaries_BT2020      = 9,  // ITU-R BT.2020 or equivalent
+  ColorPrimaries_SMPTE_ST428 = 10,  // SMPTE_240M
+  ColorPrimaries_AdobeRGB    = 11,
+  ColorPrimaries_DCIP3       = 12,
+  ColorPrimaries_EBU3213     = 22,
+  ColorPrimaries_Max         = 0xff,
+} ColorPrimaries;
+
+typedef enum GammaTransfer {
+  // Unused = 0;
+  Transfer_sRGB            = 1,  // ITR-BT.709-5
+  /* Unspecified = 2, Reserved = 3 */
+  Transfer_Gamma2_2        = 4,
+  Transfer_Gamma2_8        = 5,
+  Transfer_SMPTE_170M      = 6,  // BT.601-6 525 or 625
+  Transfer_SMPTE_240M      = 7,  // SMPTE_240M
+  Transfer_Linear          = 8,
+  Transfer_Log             = 9,
+  Transfer_Log_Sqrt        = 10,
+  Transfer_XvYCC           = 11,  // IEC 61966-2-4
+  Transfer_BT1361          = 12,  // Rec.ITU-R BT.1361 extended gamut
+  Transfer_sYCC            = 13,  // IEC 61966-2-1 sRGB or sYCC
+  Transfer_BT2020_2_1      = 14,  // Rec. ITU-R BT.2020-2 (same as the values 1, 6, and 15)
+  Transfer_BT2020_2_2      = 15,  // Rec. ITU-R BT.2020-2 (same as the values 1, 6, and 14)
+  Transfer_SMPTE_ST2084    = 16,  // 2084
+  // transfers unlikely to be required by Android
+  Transfer_ST_428          = 17,  // SMPTE ST 428-1
+  Transfer_HLG             = 18,  // ARIB STD-B67
+  Transfer_Max             = 0xff,
+} GammaTransfer;
+
+typedef enum MatrixCoEfficients {
+  MatrixCoEff_Identity           = 0,
+  MatrixCoEff_BT709_5            = 1,
+  /* Unspecified = 2, Reserved = 3 */
+  MatrixCoeff_FCC_73_682         = 4,
+  MatrixCoEff_BT601_6_625        = 5,
+  MatrixCoEff_BT601_6_525        = 6,
+  MatrixCoEff_SMPTE240M          = 7,  // used with 601_525_Unadjusted
+  MatrixCoEff_YCgCo              = 8,
+  MatrixCoEff_BT2020             = 9,
+  MatrixCoEff_BT2020Constant     = 10,
+  MatrixCoEff_BT601_6_Unadjusted = 11,  // Used with BT601_625(KR=0.222, KB=0.071)
+  MatrixCoEff_DCIP3              = 12,
+  MatrixCoEff_Chroma_NonConstant = 13,
+  MatrixCoEff_Max                = 0xff,
+} MatrixCoEfficients;
+
+typedef struct Primaries {
+  uint32_t rgbPrimaries[3][2];  // unit 1/50000;
+  uint32_t whitePoint[2];  // unit 1/50000;
+} Primaries;
+
+typedef struct MasteringDisplay {
+  bool      colorVolumeSEIEnabled;
+  Primaries primaries;
+  uint32_t  maxDisplayLuminance;  // unit: cd/m^2.
+  uint32_t  minDisplayLuminance;  // unit: 1/10000 cd/m^2.
+} MasteringDisplay;
+
+typedef struct ContentLightLevel {
+  bool     lightLevelSEIEnabled;
+  uint32_t maxContentLightLevel;  // unit: cd/m^2.
+  uint32_t minPicAverageLightLevel;  // unit: 1/10000 cd/m^2.
+} ContentLightLevel;
+
+typedef struct ColorRemappingInfo {
+  bool               criEnabled;
+  uint32_t           crId;
+  uint32_t           crCancelFlag;
+  uint32_t           crPersistenceFlag;
+  uint32_t           crVideoSignalInfoPresentFlag;
+  uint32_t           crRange;
+  ColorPrimaries     crPrimaries;
+  GammaTransfer      crTransferFunction;
+  MatrixCoEfficients crMatrixCoefficients;
+  uint32_t           crInputBitDepth;
+  uint32_t           crOutputBitDepth;
+  uint32_t           crPreLutNumValMinusOne[3];
+  uint32_t           crPreLutCodedValue[3*33];
+  uint32_t           crPreLutTargetValue[3*33];
+  uint32_t           crMatrixPresentFlag;
+  uint32_t           crLog2MatrixDenom;
+  int32_t            crCoefficients[3*3];
+  uint32_t           crPostLutNumValMinusOne[3];
+  uint32_t           crPostLutCodedValue[3*33];
+  uint32_t           crPostLutTargetValue[3*33];
+} ColorRemappingInfo;
+
+typedef struct ColorMetaData {
+  // Default values based on sRGB, needs to be overridden in gralloc
+  // based on the format and size.
+  ColorPrimaries     colorPrimaries;
+  ColorRange         range;
+  GammaTransfer      transfer;
+  MatrixCoEfficients matrixCoefficients;
+
+  MasteringDisplay   masteringDisplayInfo;
+  ContentLightLevel  contentLightLevel;
+  ColorRemappingInfo cRI;
+} ColorMetaData;
+
+typedef struct Color10Bit {
+  uint32_t R: 10;
+  uint32_t G: 10;
+  uint32_t B: 10;
+  uint32_t A: 2;
+} Color10Bit;
+
+typedef struct Lut3d {
+  uint16_t dim;  // dimension of each side of LUT cube (ex: 13, 17)in lutEntries
+  uint16_t gridSize;  // number of elements in the gridEntries
+  /* Matrix ordering convension
+  for (b = 0; b < dim; b++) {
+    for (g = 0; g < dim; g++) {
+      for (r = 0; r < dim; r++) {
+        read/write [mR mG mB] associated w/ 3DLUT[r][g][b] to/from file
+      }
+    }
+  } */
+  Color10Bit *lutEntries;
+  bool validLutEntries;  // Indicates if entries are valid and can be used.
+  /*
+   The grid is a 1D LUT for each of the R,G,B channels that can be
+   used to apply an independent nonlinear transformation to each
+   channel before it is used as a coordinate for addressing
+   the uniform 3D LUT.  This effectively creates a non-uniformly
+   sampled 3D LUT.  This is useful for having independent control
+   of the sampling grid density along each dimension for greater
+   precision in spite of having a relatively small number of samples.i
+  */
+  Color10Bit *gridEntries;
+  bool validGridEntries;  // Indicates if entries are valid and can be used.
+} Lut3d;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // __COLOR_METADATA_H__
diff --git a/sdm845/libcopybit/Android.mk b/sdm845/libcopybit/Android.mk
new file mode 100644
index 0000000..6e906c3
--- /dev/null
+++ b/sdm845/libcopybit/Android.mk
@@ -0,0 +1,53 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
+LOCAL_COPY_HEADERS            := copybit.h copybit_priv.h c2d2.h
+#Copy the headers regardless of whether copybit is built
+include $(BUILD_COPY_HEADERS)
+
+include $(CLEAR_VARS)
+ifneq ($(TARGET_USES_GRALLOC1), true)
+LOCAL_MODULE                  := copybit.$(TARGET_BOARD_PLATFORM)
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_RELATIVE_PATH    := hw
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libdl libmemalloc
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdcopybit\" -Wno-sign-conversion
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_CLANG                   := true
+
+ifeq ($(TARGET_USES_C2D_COMPOSITION),true)
+    LOCAL_CFLAGS += -DCOPYBIT_Z180=1 -DC2D_SUPPORT_DISPLAY=1
+    LOCAL_SRC_FILES := copybit_c2d.cpp software_converter.cpp
+    include $(BUILD_SHARED_LIBRARY)
+else
+    ifneq ($(call is-chipset-in-board-platform,msm7630),true)
+        ifeq ($(call is-board-platform-in-list,$(MSM7K_BOARD_PLATFORMS)),true)
+            LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1
+            LOCAL_SRC_FILES := software_converter.cpp copybit.cpp
+            include $(BUILD_SHARED_LIBRARY)
+        endif
+        ifeq ($(call is-board-platform-in-list, msm8610 msm8909),true)
+            LOCAL_SRC_FILES := software_converter.cpp copybit.cpp
+            include $(BUILD_SHARED_LIBRARY)
+        endif
+    endif
+endif
+endif
diff --git a/sdm845/libcopybit/MODULE_LICENSE_APACHE2 b/sdm845/libcopybit/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sdm845/libcopybit/MODULE_LICENSE_APACHE2
diff --git a/sdm845/libcopybit/NOTICE b/sdm845/libcopybit/NOTICE
new file mode 100644
index 0000000..9c1e63a
--- /dev/null
+++ b/sdm845/libcopybit/NOTICE
@@ -0,0 +1,189 @@
+
+   Copyright (c) 2008, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
diff --git a/sdm845/libcopybit/c2d2.h b/sdm845/libcopybit/c2d2.h
new file mode 100644
index 0000000..315a3ba
--- /dev/null
+++ b/sdm845/libcopybit/c2d2.h
@@ -0,0 +1,685 @@
+/* Copyright (c) 2010-2013, 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 __c2d2_h_
+#define __c2d2_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef C2D_API
+#define C2D_API /* define API export as needed */
+#endif
+#if !defined(int32) && !defined(_INT32_DEFINED)
+typedef int                     int32;
+#define _INT32_DEFINED
+#endif
+#if !defined(uint32) && !defined(_UINT32_DEFINED)
+typedef unsigned int            uint32;
+#define _UINT32_DEFINED
+#endif
+
+/*****************************************************************************/
+/*********************** Blit definitions *****************************/
+/*****************************************************************************/
+
+/* Status codes, returned by any blit function */
+typedef enum {
+    C2D_STATUS_OK              = 0,
+    C2D_STATUS_NOT_SUPPORTED   = 1,
+    C2D_STATUS_OUT_OF_MEMORY   = 2,
+    C2D_STATUS_INVALID_PARAM   = 3,
+    C2D_STATUS_SURFACE_IN_USE  = 4,
+} C2D_STATUS;
+
+
+/* Definitions of color format modes, used together with color formats */
+typedef enum {
+    C2D_FORMAT_PACK_INTO_32BIT   = (1 <<  8), /* pack into dword if set */
+    C2D_FORMAT_SWAP_ENDIANNESS   = (1 <<  9), /* swaps the order */
+    C2D_FORMAT_LINEAR_SPACE      = (1 << 10), /* linear color space */
+    C2D_FORMAT_PREMULTIPLIED     = (1 << 11), /* alpha premultiplied */
+    C2D_FORMAT_INVERT_ALPHA      = (1 << 12), /* inverts alpha */
+    C2D_FORMAT_DISABLE_ALPHA     = (1 << 13), /* disables alpha */
+    C2D_FORMAT_INTERLACED        = (1 << 14), /* YUV line-interlaced */
+    C2D_FORMAT_TRANSPARENT       = (1 << 15), /* YUV 1-bit alpha in Y */
+    C2D_FORMAT_MACROTILED        = (1 << 16), /* tiled in macro level */
+    C2D_FORMAT_TILED_4x4         = (1 << 17), /* 4x4 tiled format */
+    C2D_FORMAT_SWAP_RB           = (1 << 18), /* Swap R & B color components */
+    C2D_FORMAT_UBWC_COMPRESSED   = (1 << 23), /* UBWC compressed format */
+} C2D_FORMAT_MODE;
+
+/* Definitions of supported RGB formats, used in C2D_RGB_SURFACE_DEF.
+ * The bits of each color channel are packed into a machine word
+ * representing a single pixel from left to right (MSB to LSB) in the
+ * order indicated by format name. For the sub-byte formats the pixels
+ * are packed into bytes from left to right (MSbit to LSBit).
+ * If the C2D_FORMAT_PACK_INTO_32BIT bit is set, the minimal
+ * machine word used for pixel storage is 32-bit and the whole word
+ * is reversed if endianness is swapped.
+ * If the C2D_FORMAT_SWAP_ENDIANNESS bit is set, the order within a
+ * minimal machine word representing a pixel
+ * is reversed for both sub-byte and multi-byte formats.
+ * If the C2D_FORMAT_LINEAR_SPACE bit is set, the color space of
+ * the formats below is considered linear, if applicable.
+ * If the C2D_FORMAT_PREMULTIPLIED bit is set, the color channels
+ * are premultiplied with the alpha, if applicable.
+ * If the C2D_FORMAT_INVERT_ALPHA bit is set, the alpha interpretation
+ * is inverted: 0 - opaque, 1 - transparent, if applicable.
+ * If the C2D_FORMAT_DISABLE_ALPHA bit is set, the alpha channel serves
+ * as a placeholder and is ignored during blit, if applicable.
+ * If the C2D_FORMAT_MACROTILED bit is set, the surface is in the
+ * tiled format : 64x32 for 8bpp, 32x32 for 16bpp formats  */
+typedef enum {
+    C2D_COLOR_FORMAT_1            = 0,   /* 1-bit alpha/color expansion */
+
+    C2D_COLOR_FORMAT_2_PALETTE    = 1,   /* 2-bit indices for palette */
+    C2D_COLOR_FORMAT_4_PALETTE    = 2,   /* 4-bit indices for palette */
+    C2D_COLOR_FORMAT_8_PALETTE    = 3,   /* 8-bit indices for palette */
+
+    C2D_COLOR_FORMAT_2_L          = 4,   /* 2-bit grayscale */
+    C2D_COLOR_FORMAT_4_L          = 5,   /* 4-bit grayscale */
+    C2D_COLOR_FORMAT_8_L          = 6,   /* 8-bit grayscale */
+
+    C2D_COLOR_FORMAT_2_A          = 7,   /* 2-bit alpha only */
+    C2D_COLOR_FORMAT_4_A          = 8,   /* 4-bit alpha only */
+    C2D_COLOR_FORMAT_8_A          = 9,   /* 8-bit alpha only */
+
+    C2D_COLOR_FORMAT_444_RGB      = 10,  /* 12-bit colors */
+    C2D_COLOR_FORMAT_565_RGB      = 11,  /* 16-bit colors */
+    C2D_COLOR_FORMAT_888_RGB      = 12,  /* 24-bit colors */
+
+    C2D_COLOR_FORMAT_1555_ARGB    = 13,  /* 16-bit colors (1-bit alpha) */
+    C2D_COLOR_FORMAT_4444_ARGB    = 14,  /* 16-bit colors (4-bit alpha) */
+    C2D_COLOR_FORMAT_8565_ARGB    = 15,  /* 24-bit colors (8-bit alpha) */
+    C2D_COLOR_FORMAT_8888_ARGB    = 16,  /* 32-bit colors (8-bit alpha) */
+
+    C2D_COLOR_FORMAT_5551_RGBA    = 17,  /* 16-bit colors (1-bit alpha) */
+    C2D_COLOR_FORMAT_4444_RGBA    = 18,  /* 16-bit colors (4-bit alpha) */
+    C2D_COLOR_FORMAT_5658_RGBA    = 19,  /* 24-bit colors (8-bit alpha) */
+    C2D_COLOR_FORMAT_8888_RGBA    = 20,  /* 32-bit colors (8-bit alpha) */
+
+    /* derived RGB color formats (base format + mode bits) */
+
+} C2D_RGB_FORMAT;
+
+/* Definitions of supported YUV formats, used in C2D_YUV_SURFACE_DEF.
+ * Each of Y,U,V channels usually takes 1 byte and therefore is
+ * individually addressable. The definitions below show how Y,U,V
+ * channels are packed into macropixels for each particular format.
+ * The order is from left (smaller byte addresses) to right (larger
+ * byte addresses). The first three digits (4xx) denote the chroma
+ * subsampling in standard YUV notation. The digits in the macropixel
+ * denote that the whole block (from the previous digit or from the
+ * beginning) has to be repeated the number of times. Underscores
+ * between Y,U,V channels are used to describe separate planes for
+ * planar YUV formats. Formats are mapped to numbers so that future
+ * versions with various YUV permutations are easy to add.
+ * If the C2D_FORMAT_INTERLACED bit is set, the line order is
+ * interlaced: 0,2,4,...1,3,5... if applicable.
+ * If the C2D_FORMAT_TRANSPARENT bit is set, the least significant
+ * bit of Y channel serves as alpha: 0 - transparent, 1 - opaque. */
+typedef enum {
+    C2D_COLOR_FORMAT_411_YYUYYV   = 110, /* packed, 12-bit         */
+    C2D_COLOR_FORMAT_411_YUYYVY   = 111, /* packed, 12-bit         */
+    C2D_COLOR_FORMAT_411_UYYVYY   = 112, /* packed, 12-bit, "Y411" */
+    C2D_COLOR_FORMAT_411_YUYV2Y4  = 116, /* packed, 12-bit         */
+    C2D_COLOR_FORMAT_411_UYVY2Y4  = 117, /* packed, 12-bit, "Y41P" */
+
+    C2D_COLOR_FORMAT_422_YUYV     = 120, /* packed, 16-bit, "YUY2" */
+    C2D_COLOR_FORMAT_422_UYVY     = 121, /* packed, 16-bit, "UYVY" */
+    C2D_COLOR_FORMAT_422_YVYU     = 122, /* packed, 16-bit, "YVYU" */
+    C2D_COLOR_FORMAT_422_VYUY     = 123, /* packed, 16-bit         */
+
+    C2D_COLOR_FORMAT_444_YUV      = 130, /* packed, 24-bit         */
+    C2D_COLOR_FORMAT_444_UYV      = 131, /* packed, 24-bit, "IYU2" */
+    C2D_COLOR_FORMAT_444_AYUV     = 136, /* packed, 24-bit, "AYUV" */
+
+    C2D_COLOR_FORMAT_410_Y_UV     = 150, /* planar, Y + interleaved UV */
+    C2D_COLOR_FORMAT_411_Y_UV     = 151, /* planar, Y + interleaved UV */
+    C2D_COLOR_FORMAT_420_Y_UV     = 152, /* planar, Y + interleaved UV */
+    C2D_COLOR_FORMAT_422_Y_UV     = 153, /* planar, Y + interleaved UV */
+    C2D_COLOR_FORMAT_444_Y_UV     = 154, /* planar, Y + interleaved UV */
+
+    C2D_COLOR_FORMAT_410_Y_VU     = 160, /* planar, Y + interleaved VU */
+    C2D_COLOR_FORMAT_411_Y_VU     = 161, /* planar, Y + interleaved VU */
+    C2D_COLOR_FORMAT_420_Y_VU     = 162, /* planar, Y + interleaved VU */
+    C2D_COLOR_FORMAT_422_Y_VU     = 163, /* planar, Y + interleaved VU */
+    C2D_COLOR_FORMAT_444_Y_VU     = 164, /* planar, Y + interleaved VU */
+
+    C2D_COLOR_FORMAT_410_Y_U_V    = 170, /* planar, Y + U + V separate */
+    C2D_COLOR_FORMAT_411_Y_U_V    = 171, /* planar, Y + U + V separate */
+    C2D_COLOR_FORMAT_420_Y_V_U    = 172, /* planar, Y + V + U separate */
+    C2D_COLOR_FORMAT_420_Y_U_V    = 173, /* planar, Y + U + V separate */
+    C2D_COLOR_FORMAT_422_Y_U_V    = 174, /* planar, Y + U + V separate */
+    C2D_COLOR_FORMAT_444_Y_U_V    = 175, /* planar, Y + U + V separate */
+
+    C2D_COLOR_FORMAT_800_Y        = 190, /* planar, Y only, grayscale */
+
+    /* derived YUV color formats (base format + mode bits), FOURCC */
+
+    C2D_COLOR_FORMAT_411_Y411     = 112,
+    C2D_COLOR_FORMAT_411_Y41P     = 117,
+    C2D_COLOR_FORMAT_411_IY41     = 117 | (1 << 14),
+    C2D_COLOR_FORMAT_411_Y41T     = 117 | (1 << 15),
+
+    C2D_COLOR_FORMAT_422_YUY2     = 120,
+    C2D_COLOR_FORMAT_422_IUYV     = 121 | (1 << 14),
+    C2D_COLOR_FORMAT_422_Y42T     = 121 | (1 << 15),
+    C2D_COLOR_FORMAT_444_IYU2     = 131,
+
+    C2D_COLOR_FORMAT_420_NV12     = 152,
+    C2D_COLOR_FORMAT_420_NV21     = 162,
+
+    C2D_COLOR_FORMAT_410_YUV9     = 170,
+    C2D_COLOR_FORMAT_410_YVU9     = 170,
+    C2D_COLOR_FORMAT_411_Y41B     = 171,
+    C2D_COLOR_FORMAT_420_YV12     = 172,
+    C2D_COLOR_FORMAT_420_IYUV     = 173,
+    C2D_COLOR_FORMAT_420_I420     = 173,
+    C2D_COLOR_FORMAT_422_YV16     = 174,
+    C2D_COLOR_FORMAT_422_Y42B     = 174,
+
+    C2D_COLOR_FORMAT_800_Y800     = 190,
+
+} C2D_YUV_FORMAT;
+
+
+/* Configuration bits, used in the config_mask field of C2D_OBJECT struct */
+typedef enum {
+    C2D_SOURCE_RECT_BIT      = (1 <<  0), /* enables source_rect field */
+    C2D_MIRROR_H_BIT         = (1 <<  1), /* enables horizontal flipping */
+    C2D_MIRROR_V_BIT         = (1 <<  2), /* enables vertical flipping */
+    C2D_SOURCE_TILE_BIT      = (1 <<  3), /* enables source surface tiling */
+    C2D_TARGET_RECT_BIT      = (1 <<  4), /* enables target_rect field */
+    C2D_ROTATE_BIT           = (1 <<  5), /* enables all rotation fields */
+    C2D_SCISSOR_RECT_BIT     = (1 <<  6), /* enables scissor_rect field */
+    C2D_MASK_SURFACE_BIT     = (1 <<  7), /* enables mask_surface_id field */
+    C2D_MASK_ALIGN_BIT       = (1 <<  8), /* aligns mask to source_rect */
+    C2D_MASK_SCALE_BIT       = (1 <<  9), /* enables mask surface scaling */
+    C2D_MASK_TILE_BIT        = (1 << 10), /* enables mask surface tiling */
+    C2D_GLOBAL_ALPHA_BIT     = (1 << 11), /* enables global_alpha field */
+    C2D_COLOR_KEY_BIT        = (1 << 12), /* enables color_key field */
+    C2D_NO_PIXEL_ALPHA_BIT   = (1 << 13), /* disables source alpha channel */
+    C2D_NO_BILINEAR_BIT      = (1 << 14), /* disables bilinear on scaling */
+    C2D_NO_ANTIALIASING_BIT  = (1 << 15), /* disables antialiasing on edges */
+    C2D_DRAW_LINE_BIT        = (1 << 16), /* enables line drawing with source rectangle */
+    C2D_DRAW_LINE_NOLAST     = (1 << 17), /* disable last pixel draw for line */
+} C2D_SOURCE_CONFIG;
+
+
+/* Target configuration bits, defines rotation + mirroring.
+ * Mirror is applied prior to rotation if enabled. */
+typedef enum {
+    C2D_TARGET_MIRROR_H        = (1 << 0), /* horizontal flip */
+    C2D_TARGET_MIRROR_V        = (1 << 1), /* vertical flip */
+    C2D_TARGET_ROTATE_0        = (0 << 2), /* no rotation */
+    C2D_TARGET_ROTATE_90       = (1 << 2), /* 90 degree rotation */
+    C2D_TARGET_ROTATE_180      = (2 << 2), /* 180 degree rotation */
+    C2D_TARGET_ROTATE_270      = (3 << 2), /* 270 degree rotation, 90 + 180 */
+    C2D_TARGET_MASK_ALIGN      = (1 << 4), /* aligns mask to target scissor */
+    C2D_TARGET_MASK_SCALE      = (1 << 5), /* enables mask scaling */
+    C2D_TARGET_MASK_TILE       = (1 << 6), /* enables mask tiling */
+    C2D_TARGET_COLOR_KEY       = (1 << 7), /* enables target_color_key */
+    C2D_TARGET_NO_PIXEL_ALPHA  = (1 << 8), /* disables target alpha channel */
+} C2D_TARGET_CONFIG;
+
+#define C2D_TARGET_ROTATION_MASK  (C2D_TARGET_ROTATE_90*3)
+
+/* Additional blend modes, can be used with both source and target configs.
+   If none of the below is set, the default "SRC over DST" is applied. */
+typedef enum {
+    C2D_ALPHA_BLEND_SRC_OVER   = (0  << 20), /* Default, Porter-Duff "SRC over DST" */
+    C2D_ALPHA_BLEND_SRC        = (1  << 20), /* Porter-Duff "SRC" */
+    C2D_ALPHA_BLEND_SRC_IN     = (2  << 20), /* Porter-Duff "SRC in DST" */
+    C2D_ALPHA_BLEND_DST_IN     = (3  << 20), /* Porter-Duff "DST in SRC" */
+    C2D_ALPHA_BLEND_SRC_OUT    = (4  << 20), /* Porter-Duff "SRC out DST" */
+    C2D_ALPHA_BLEND_DST_OUT    = (5  << 20), /* Porter-Duff "DST out SRC" */
+    C2D_ALPHA_BLEND_DST_OVER   = (6  << 20), /* Porter-Duff "DST over SRC" */
+    C2D_ALPHA_BLEND_SRC_ATOP   = (7  << 20), /* Porter-Duff "SRC ATOP" */
+    C2D_ALPHA_BLEND_DST_ATOP   = (8  << 20), /* Porter-Duff "DST ATOP" */
+    C2D_ALPHA_BLEND_XOR        = (9  << 20), /* Xor */
+    C2D_ALPHA_BLEND_MULTIPLY   = (10 << 20), /* OpenVG "MULTIPLY" */
+    C2D_ALPHA_BLEND_SCREEN     = (11 << 20), /* OpenVG "SCREEN" */
+    C2D_ALPHA_BLEND_DARKEN     = (12 << 20), /* OpenVG "DARKEN" */
+    C2D_ALPHA_BLEND_LIGHTEN    = (13 << 20), /* OpenVG "LIGHTEN" */
+    C2D_ALPHA_BLEND_ADDITIVE   = (14 << 20), /* OpenVG "ADDITIVE" */
+    C2D_ALPHA_BLEND_DIRECT     = (15 << 20), /* Direct alpha blitting */
+    C2D_ALPHA_BLEND_INVERTC    = (16 << 20), /* Invert color */
+    C2D_ALPHA_BLEND_NONE       = (1  << 25), /* disables alpha blending */
+} C2D_ALPHA_BLEND_MODE;
+
+/* Configuration bits, used in the config_mask field of C2D_OBJECT struct */
+typedef enum {
+    C2D_OVERRIDE_GLOBAL_TARGET_ROTATE_CONFIG = (1 << 27), /* Overrides TARGET Config */
+    C2D_OVERRIDE_TARGET_ROTATE_0             = (0 << 28), /* no rotation             */
+    C2D_OVERRIDE_TARGET_ROTATE_90            = (1 << 28), /* 90 degree rotation      */
+    C2D_OVERRIDE_TARGET_ROTATE_180           = (2 << 28), /* 180 degree rotation     */
+    C2D_OVERRIDE_TARGET_ROTATE_270           = (3 << 28), /* 270 degree rotation     */
+} C2D_SOURCE_TARGET_CONFIG;
+
+#define C2D_OVERRIDE_SOURCE_CONFIG_TARGET_ROTATION_SHIFT_MASK  28
+#define C2D_OVERRIDE_TARGET_CONFIG_TARGET_ROTATION_SHIFT_MASK  2
+
+
+/* Surface caps enumeration */
+typedef enum {
+    C2D_SOURCE          = (1 << 0), /* allows to use as a source */
+    C2D_TARGET          = (1 << 1), /* allows to use as a target */
+    C2D_MASK            = (1 << 2), /* allows to use as a mask */
+    C2D_PALETTE         = (1 << 3), /* allows to use as a palette */
+} C2D_SURFACE_BITS;
+
+/* Surface type enumeration */
+typedef enum {
+    C2D_SURFACE_RGB_HOST        = 1, /* Host memory RGB surface */
+    C2D_SURFACE_RGB_EXT         = 2, /* External memory RGB surface */
+    C2D_SURFACE_YUV_HOST        = 3, /* Host memory YUV surface */
+    C2D_SURFACE_YUV_EXT         = 4, /* External memory YUV surface */
+    C2D_SURFACE_WITH_PHYS       = (1<<3), /* physical address already mapped */
+                                        /* this bit is valid with HOST types */
+    C2D_SURFACE_WITH_PHYS_DUMMY = (1<<4), /* physical address already mapped */
+                                        /* this bit is valid with HOST types */
+} C2D_SURFACE_TYPE;
+
+/* Structure for registering a RGB buffer as a blit surface */
+typedef struct {
+    uint32 format;   /* RGB color format plus additional mode bits */
+    uint32 width;    /* defines width in pixels */
+    uint32 height;   /* defines height in pixels */
+    void  *buffer;   /* pointer to the RGB buffer */
+    void  *phys;     /* physical address */
+    int32  stride;   /* defines stride in bytes, negative stride is allowed */
+} C2D_RGB_SURFACE_DEF;
+
+/* Structure for registering a YUV plane(s) as a blit surface */
+typedef struct {
+    uint32 format;   /* YUV color format plus additional mode bits */
+    uint32 width;    /* defines width in pixels */
+    uint32 height;   /* defines height in pixels */
+    void  *plane0;  /* holds the whole buffer if YUV format is not planar */
+    void  *phys0;   /* physical address */
+    int32  stride0; /* stride in bytes if YUV format is not planar */
+    void  *plane1;  /* holds UV or VU plane for planar interleaved */
+    void  *phys1;   /* physical address */
+    int32  stride1; /* stride for UV or VU plane for planar interleaved */
+    void  *plane2;  /* holds the 3. plane, ignored if YUV format is not planar */
+    void  *phys2;    /* physical address */
+    int32  stride2; /* stride for the 3. plane, ignored if YUV format is not planar */
+} C2D_YUV_SURFACE_DEF;
+
+
+/* Rectangle definition */
+typedef struct {
+    int32 x;        /* upper-left x */
+    int32 y;        /* upper-left y */
+    int32 width;    /* width */
+    int32 height;   /* height */
+} C2D_RECT;
+
+/* C2D_OBJECT encapsulates the blit parameters for a source surface.
+ * The fg_color defines color in target format for bits equal to 1
+ * in the source C2D_COLOR_FORMAT_1 format. It also defines rendering
+ * color for all alpha-only source formats. If the surface_id is 0
+ * the fg_color defines a constant fill color used instead of the surface.
+ * The bg_color defines color in target format for bits equal to 0
+ * in the source C2D_COLOR_FORMAT_1 format, otherwise both are ignored.
+ * The palette_id is used for all palette source formats, otherwise ignored.
+
+ * The source_rect first defines the content of the source surface,
+ * it is then horizontally/vertically flipped if C2D_MIRROR_*_BIT is set,
+ * then scaled with bilinear interpolation to exactly fit target_rect
+ * or repeated across target_rect if C2D_SOURCE_TILE_BIT is set,
+ * target_rect is then rotated clockwise by an arbitrary angle in degrees
+ * around the rot_orig_x/y, defined relative to target_rect's top left point,
+ * and then clipped to scissor_rect defined in target coordinate system.
+
+ * Finally alpha blending is applied before pixels get written into the target.
+ * Surface's pixel alpha is combined with mask alpha and with global alpha.
+ * Mask surface follows all transformations applied to the source surface.
+ * Source color key defines transparent color, applied together with alpha. */
+typedef struct C2D_OBJECT_STR {
+    uint32 surface_id;      /* source surface */
+
+    uint32 fg_color;        /* foreground color */
+    uint32 bg_color;        /* background color */
+    uint32 palette_id;      /* one-dimensional horizontal palette surface */
+
+    uint32 config_mask;     /* defines which fields below are enabled */
+
+    C2D_RECT source_rect;  /* region of the source surface,   16.16 fp */
+    C2D_RECT target_rect;  /* position and scaling in target, 16.16 fp */
+
+    int32 rot_orig_x;       /* rotation origin relative to target_rect's... */
+    int32 rot_orig_y;       /* ...top left point,     both are 16.16 fp */
+    int32 rotation;         /* clock-wise rotation in degrees, 16.16 fp */
+
+    C2D_RECT scissor_rect; /* defines the clip rectangle in target surface */
+
+    uint32 mask_surface_id; /* source alpha-mask surface */
+    uint32 global_alpha;    /* 0 = fully transparent, 255 = fully opaque */
+    uint32 color_key;       /* transparent color for the source surface */
+
+    struct C2D_OBJECT_STR *next; /* pointer to the next object or NULL */
+} C2D_OBJECT;
+
+/* Configuration bits, driver capabilities used by 2Dapplications */
+typedef enum {
+    C2D_DRIVER_SUPPORTS_GLOBAL_ALPHA_OP           = (1 << 0),
+    C2D_DRIVER_SUPPORTS_TILE_OP                   = (1 << 1),
+    C2D_DRIVER_SUPPORTS_COLOR_KEY_OP              = (1 << 2),
+    C2D_DRIVER_SUPPORTS_NO_PIXEL_ALPHA_OP         = (1 << 3),
+    C2D_DRIVER_SUPPORTS_TARGET_ROTATE_OP          = (1 << 4),
+    C2D_DRIVER_SUPPORTS_ANTI_ALIASING_OP          = (1 << 5), /* antialiasing */
+    C2D_DRIVER_SUPPORTS_BILINEAR_FILTER_OP        = (1 << 6),
+    C2D_DRIVER_SUPPORTS_LENS_CORRECTION_OP        = (1 << 7),
+    C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP = (1 << 8),
+    C2D_DRIVER_SUPPORTS_SHADER_BLOB_OP            = (1 << 9),
+    C2D_DRIVER_SUPPORTS_MASK_SURFACE_OP           = (1 << 10), /* mask surface */
+    C2D_DRIVER_SUPPORTS_MIRROR_H_OP               = (1 << 11), /* horizontal flip */
+    C2D_DRIVER_SUPPORTS_MIRROR_V_OP               = (1 << 12), /* vertical flip */
+    C2D_DRIVER_SUPPORTS_SCISSOR_RECT_OP           = (1 << 13),
+    C2D_DRIVER_SUPPORTS_SOURCE_RECT_OP            = (1 << 14),
+    C2D_DRIVER_SUPPORTS_TARGET_RECT_OP            = (1 << 15),
+    C2D_DRIVER_SUPPORTS_ROTATE_OP                 = (1 << 16), /* all rotations */
+    C2D_DRIVER_SUPPORTS_FLUSH_WITH_FENCE_FD_OP    = (1 << 17), /* all rotations */
+    C2D_DRIVER_SUPPORTS_UBWC_COMPRESSED_OP        = (1 << 18), /* UBWC Compression */
+    C2D_DRIVER_SUPPORTS_ALL_CAPABILITIES_OP       = ((0xFFFFFFFF) >> (31 - 18)) /* mask for all capabilities supported */
+} C2D_DRIVER_CAPABILITIES;
+
+/* 2D driver workaround bits used by the 2D applications */
+typedef enum {
+    C2D_DRIVER_WORKAROUND_NONE  = 0, /* NO workaround */
+    C2D_DRIVER_WORKAROUND_SWAP_UV_FOR_YUV_TARGET  = (1 << 0), /* Swap UV when this flag set */
+} C2D_DRIVER_WORKAROUND;
+
+/* Structure to query Driver information */
+typedef struct {
+    uint32 capabilities_mask;
+    uint32 workaround_mask;
+    uint32 reserved1;
+    uint32 reserved2;
+    uint32 reserved3;
+} C2D_DRIVER_INFO;
+
+/* Structure to query Driver information */
+typedef struct {
+    uint32          max_surface_template_needed;
+    uint32          reserved1;
+    uint32          reserved2;
+    uint32          reserved3;
+} C2D_DRIVER_SETUP_INFO;
+
+/*****************************************************************************/
+/**************************** C2D API 2.0 ********************************/
+/*****************************************************************************/
+
+/******************************************************************************
+ * Functions to create/destroy surfaces */
+
+/* Creates a generic blit surface according to its type.
+ * Pass a combination of desired surface bits according to planned usage.
+ * Accepted values for surface_bits may include bits from C2D_SURFACE_BITS,
+ * and also from C2D_DISPLAY for compatibility with HW display controller.
+ * For host memory types the memory is preallocated outside the API
+ * and should remain valid until surface is destroyed.
+ * For external memory types the memory is allocated within API.
+ * On success, the non-zero surface identifier is returned.
+ * All numbers greater that 0 are valid surface identifiers, 0 is invalid.
+
+ * Host memory RGB surface:
+ * surface_type       = C2D_SURFACE_RGB_HOST
+ * surface_definition = C2D_RGB_SURFACE_DEF
+ * all fields in definition structure should be set
+
+ * External memory RGB surface:
+ * surface_type       = C2D_SURFACE_RGB_EXT
+ * surface_definition = C2D_RGB_SURFACE_DEF
+ * buffer field in definition structure is ignored
+
+ * Host memory YUV surface:
+ * surface_type       = C2D_SURFACE_YUV_HOST
+ * surface_definition = C2D_YUV_SURFACE_DEF
+ * one or all plane and stride fields in definition structure
+ * should be set depending on whether the format is planar or not
+
+ * External memory YUV surface:
+ * surface_type       = C2D_SURFACE_YUV_EXT
+ * surface_definition = C2D_YUV_SURFACE_DEF
+ * all plane and stride fields in definition structure are ignored */
+C2D_API C2D_STATUS c2dCreateSurface( uint32 *surface_id,
+                         uint32 surface_bits,
+                         C2D_SURFACE_TYPE surface_type,
+                         void *surface_definition );
+
+/* Requests properties of the specified surface. */
+C2D_API C2D_STATUS c2dQuerySurface( uint32 surface_id,
+                         uint32 *surface_bits,
+                         C2D_SURFACE_TYPE *surface_type,
+                         uint32 *width, uint32 *height,
+                         uint32 *format );
+
+/* Destroys a generic blit surface.
+ * For external memory surfaces also deallocates the memory.
+ * It is safe to free any external resources associated with a given
+ * surface on c2dCreateSurface call after this function returns. */
+C2D_API C2D_STATUS c2dDestroySurface( uint32 surface_id );
+
+
+/******************************************************************************
+ * Functions to modify/exchange surface data */
+
+/* The format of fill_color is the same as color format being used
+ * for specified surface. If fill_rect is NULL the whole surface is filled.
+ * Alpha-blending is not performed while filling.
+ * The operation is complete when function returns. */
+C2D_API C2D_STATUS c2dFillSurface( uint32 surface_id,
+                         uint32 fill_color,
+                         C2D_RECT *fill_rect );
+
+/* Writes data located in host memory into the specified surface.
+ * The chunk of host memory is identified with surface_type and
+ * surface_definition, no surface registration needed in this case.
+ * Only C2D_SURFACE_RGB_HOST, C2D_SURFACE_YUV_HOST are accepted.
+ * If only part of the host memory buffer should be loaded, it should
+ * be configured in surface_definition using width, height and stride.
+ * The x and y are defined in target surface coordinate space.
+ * Color conversion has to be done, if color formats differ.
+ * Alpha-blending is not performed while writing.
+ * The operation is complete when function returns. */
+C2D_API C2D_STATUS c2dWriteSurface( uint32 surface_id,
+                         C2D_SURFACE_TYPE surface_type,
+                         void *surface_definition,
+                         int32 x, int32 y );
+
+/* Reads data from the specified surface into the host memory.
+ * The chunk of host memory is identified with surface_type and
+ * surface_definition, no surface registration needed in this case.
+ * Only C2D_SURFACE_RGB_HOST, C2D_SURFACE_YUV_HOST are accepted.
+ * If only part of the surface should be read, it should
+ * be configured in surface_definition using width, height and stride.
+ * The x and y are defined in source surface coordinate space.
+ * Color conversion has to be done, if color formats differ.
+ * Alpha-blending is not performed while reading.
+ * The operation is complete when function returns. */
+C2D_API C2D_STATUS c2dReadSurface( uint32 surface_id,
+                         C2D_SURFACE_TYPE surface_type,
+                         void *surface_definition,
+                         int32 x, int32 y );
+
+/* Notifies c2d imlementation that surface has been updated from outside the API,
+ * if updated_rect is NULL then the whole surface has been updated. */
+C2D_API C2D_STATUS c2dSurfaceUpdated( uint32 surface_id,
+                         C2D_RECT *updated_rect );
+
+/* Updates surface information.
+ * Could be called only for host surfaces set with parameter "C2D_SURFACE_WITH_PHYS".
+ * Count for surface planes have to be same than for already allocated surface */
+C2D_API C2D_STATUS c2dUpdateSurface( uint32 surface_id,
+                         uint32 surface_bits,
+                         C2D_SURFACE_TYPE surface_type,
+                         void *surface_definition );
+
+/******************************************************************************
+ * Functions to do actual blit */
+
+/* Draw a list of blit objects into the given target.
+ * The target_config is a bitwise OR of values from C2D_TARGET_CONFIG.
+ * The target transformation creates the effect that target surface
+ * is transformed before the blit and then transformed back
+ * after blit, however no physical target transform is performed.
+ * The objects_list is a linked list of blit objects, no more
+ * than num_objects is drawn from the given list.
+ * If num_objects is 0, the whole list is drawn.
+ * The blit is not guaranteed to complete after function returns. */
+C2D_API C2D_STATUS c2dDraw( uint32 target_id,
+                         uint32 target_config, C2D_RECT *target_scissor,
+                         uint32 target_mask_id, uint32 target_color_key,
+                         C2D_OBJECT *objects_list, uint32 num_objects );
+
+
+/* timstamp set in the blit commands flush */
+typedef void*                   c2d_ts_handle;
+
+/* Forces any pending blit to complete for a given target.
+ * Non-blocking. All input surfaces for this target except those
+ * which are shared with other targets are expected to be immediately
+ * writable after client has been waiting returned timestamp with
+ * c2dWaitTimestamp funtion or c2dFinish has been called for same target */
+C2D_API C2D_STATUS c2dFlush( uint32 target_id, c2d_ts_handle *timestamp);
+
+
+/* Waits the pending timestamp */
+C2D_API C2D_STATUS c2dWaitTimestamp( c2d_ts_handle timestamp );
+
+
+/* Forces any pending blit to complete for a given target.
+ * Blocking version, returns when blit is done.
+ * All input surfaces for this target except those which are shared with
+ * other targets are expected to be immediately
+ * writable after this function returns. */
+C2D_API C2D_STATUS c2dFinish( uint32 target_id );
+
+
+/*****************************************************************************/
+/****************************** Display API **********************************/
+/*****************************************************************************/
+
+
+/* Display input enumeration */
+typedef enum {
+    C2D_DISPLAY_INPUT_0      = 0,       /*!< default input */
+    C2D_DISPLAY_INPUT_1      = (1<<16), /*!< Overlay 1     */
+    C2D_DISPLAY_INPUT_2      = (1<<17), /*!< Overlay 2...    */
+} C2D_DISPLAY_INPUT;
+
+
+/******************************************************************************
+ * Functions for display output. */
+
+/* Functionality described in this section is optional and is
+ * provided only for the cases when blit HW
+ * is tightly bound to the display controller. */
+
+/* Display enumeration, may also be used in surface caps */
+typedef enum {
+    C2D_DISPLAY_MAIN         = (1 << 10), /* main display */
+    C2D_DISPLAY_SECONDARY    = (1 << 11), /* secondary display */
+    C2D_DISPLAY_TV_OUT       = (1 << 12), /* tv-out */
+} C2D_DISPLAY;
+
+/* Display window enumeration */
+typedef enum {
+    C2D_DISPLAY_OVERLAY      = C2D_DISPLAY_INPUT_1, /*!< Overlay window bit. This defines display input.
+                                                When defined the surface is set on the overlay window
+                                                otherwise the surface is set on the background window. */
+} C2D_DISPLAY_WINDOW;                    /*!< Window bit set with display parameter */
+
+
+/* Display update modes */
+typedef enum {
+    C2D_DISPLAY_MODE_TEAR_SYNC   = (1 << 0), /* enables tearing sync */
+    C2D_DISPLAY_MODE_SURF_REMOVE = (1 << 1), /* Remove surface from given display + input */
+} C2D_DISPLAY_MODE;
+
+
+/* Sets the given surface as a current display front buffer.
+ * Several displays can be specified as an output if supported.
+ * Still only one input can be specified at a time fro display/displays.
+ * The surface remains shown until it gets replaced with another one. */
+C2D_API C2D_STATUS c2dDisplaySetSurface( uint32 display,
+                         uint32 surface_id, uint32 mode );
+
+/* Returns the current surface for a particular display.
+ * Only one display can be specified at a time.
+ * The latest surface set with compDisplaySetSurface or
+ * the default pre-allocated surface is returned. */
+C2D_API C2D_STATUS c2dDisplayGetSurface( uint32 display,
+                         uint32 *surface_id );
+
+/* Returns the properties for a particular display.
+ * Only one display can be specified at a time. */
+C2D_API C2D_STATUS c2dDisplayGetProperties( uint32 display,
+                         uint32 *width, uint32 *height,
+                         uint32 *format );
+
+/* Sets the properties for a particular display input.
+ * Only one display + input can be specified at a time.
+ * C2D_OBJECT used to set input rect(target rect),
+ * blending operations, rotation...etc for display source */
+C2D_API C2D_STATUS c2dDisplaySetObject( uint32 display,
+                         uint32 target_config, uint32 target_color_key,
+                         C2D_OBJECT * c2dObject, uint32 mode);
+
+/* allows user to map a memory region to the gpu. only supported on linux
+ * mem_fd is the fd of the memory region, hostptr is the host pointer to the region,
+ * len and offset are the size and offset of the memory.
+ * flags is one of the memory types supported by gsl
+ * gpaddr is passed by refernce back to the user
+ */
+C2D_API C2D_STATUS c2dMapAddr ( int mem_fd, void * hostptr, uint32 len, uint32 offset, uint32 flags, void ** gpuaddr);
+
+/* allows user to unmap memory region mapped by c2dMapAddr.
+ * gpaddr is the gpuaddr to unmap */
+C2D_API C2D_STATUS c2dUnMapAddr (void * gpuaddr);
+
+/* allows user to query driver capabilities.
+ * driver_info is the information about driver */
+C2D_API C2D_STATUS c2dGetDriverCapabilities( C2D_DRIVER_INFO * driver_info);
+
+/* create a fence fd for the timestamp */
+C2D_API C2D_STATUS c2dCreateFenceFD( uint32 target_id, c2d_ts_handle timestamp, int32 *fd);
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __c2d2_h_ */
diff --git a/sdm845/libcopybit/copybit.cpp b/sdm845/libcopybit/copybit.cpp
new file mode 100644
index 0000000..80b3cfe
--- /dev/null
+++ b/sdm845/libcopybit/copybit.cpp
@@ -0,0 +1,794 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010 - 2014, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cutils/log.h>
+
+#include <linux/msm_mdp.h>
+#include <linux/fb.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <copybit.h>
+
+#include "gralloc_priv.h"
+#include "software_converter.h"
+#include <qdMetaData.h>
+
+#define DEBUG_MDP_ERRORS 1
+
+/******************************************************************************/
+
+#define MAX_SCALE_FACTOR    (4)
+#define MAX_DIMENSION       (4096)
+
+/******************************************************************************/
+struct blitReq{
+    struct  mdp_buf_sync sync;
+    uint32_t count;
+    struct mdp_blit_req req[10];
+};
+
+/** State information for each device instance */
+struct copybit_context_t {
+    struct copybit_device_t device;
+    int     mFD;
+    uint8_t mAlpha;
+    int     mFlags;
+    bool    mBlitToFB;
+    int     acqFence[MDP_MAX_FENCE_FD];
+    int     relFence;
+    struct  mdp_buf_sync sync;
+    struct  blitReq list;
+    uint8_t dynamic_fps;
+};
+
+/**
+ * Common hardware methods
+ */
+
+static int open_copybit(const struct hw_module_t* module, const char* name,
+                        struct hw_device_t** device);
+
+static struct hw_module_methods_t copybit_module_methods = {
+open:  open_copybit
+};
+
+/*
+ * The COPYBIT Module
+ */
+struct copybit_module_t HAL_MODULE_INFO_SYM = {
+common: {
+tag: HARDWARE_MODULE_TAG,
+     version_major: 1,
+     version_minor: 0,
+     id: COPYBIT_HARDWARE_MODULE_ID,
+     name: "QCT MSM7K COPYBIT Module",
+     author: "Google, Inc.",
+     methods: &copybit_module_methods
+        }
+};
+
+/******************************************************************************/
+
+/** min of int a, b */
+static inline int min(int a, int b) {
+    return (a<b) ? a : b;
+}
+
+/** max of int a, b */
+static inline int max(int a, int b) {
+    return (a>b) ? a : b;
+}
+
+/** scale each parameter by mul/div. Assume div isn't 0 */
+static inline void MULDIV(uint32_t *a, uint32_t *b, int mul, int div) {
+    if (mul != div) {
+        *a = (mul * *a) / div;
+        *b = (mul * *b) / div;
+    }
+}
+
+/** Determine the intersection of lhs & rhs store in out */
+static void intersect(struct copybit_rect_t *out,
+                      const struct copybit_rect_t *lhs,
+                      const struct copybit_rect_t *rhs) {
+    out->l = max(lhs->l, rhs->l);
+    out->t = max(lhs->t, rhs->t);
+    out->r = min(lhs->r, rhs->r);
+    out->b = min(lhs->b, rhs->b);
+}
+
+static bool validateCopybitRect(struct copybit_rect_t *rect) {
+    return ((rect->b > rect->t) && (rect->r > rect->l)) ;
+}
+
+/** convert COPYBIT_FORMAT to MDP format */
+static int get_format(int format) {
+    switch (format) {
+        case HAL_PIXEL_FORMAT_RGB_565:       return MDP_RGB_565;
+        case HAL_PIXEL_FORMAT_RGBA_5551:     return MDP_RGBA_5551;
+        case HAL_PIXEL_FORMAT_RGBA_4444:     return MDP_RGBA_4444;
+        case HAL_PIXEL_FORMAT_RGBX_8888:     return MDP_RGBX_8888;
+        case HAL_PIXEL_FORMAT_BGRX_8888:     return MDP_BGRX_8888;
+        case HAL_PIXEL_FORMAT_RGB_888:       return MDP_RGB_888;
+        case HAL_PIXEL_FORMAT_RGBA_8888:     return MDP_RGBA_8888;
+        case HAL_PIXEL_FORMAT_BGRA_8888:     return MDP_BGRA_8888;
+        case HAL_PIXEL_FORMAT_YCrCb_422_I:   return MDP_YCRYCB_H2V1;
+        case HAL_PIXEL_FORMAT_YCbCr_422_I:   return MDP_YCBYCR_H2V1;
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:  return MDP_Y_CRCB_H2V1;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:  return MDP_Y_CRCB_H2V2;
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:  return MDP_Y_CBCR_H2V1;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:  return MDP_Y_CBCR_H2V2;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: return MDP_Y_CBCR_H2V2_ADRENO;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: return MDP_Y_CBCR_H2V2_VENUS;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: return MDP_Y_CRCB_H2V2_VENUS;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: return MDP_Y_CBCR_H2V2;
+        case HAL_PIXEL_FORMAT_CbYCrY_422_I: return MDP_CBYCRY_H2V1;
+        case HAL_PIXEL_FORMAT_BGR_888: return MDP_BGR_888;
+    }
+    return -1;
+}
+
+/** convert from copybit image to mdp image structure */
+static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs)
+{
+    private_handle_t* hnd = (private_handle_t*)rhs->handle;
+    if(hnd == NULL){
+        ALOGE("copybit: Invalid handle");
+        return;
+    }
+    img->width      = rhs->w;
+    img->height     = rhs->h;
+    img->format     = get_format(rhs->format);
+    img->offset     = (uint32_t)hnd->offset;
+    img->memory_id  = hnd->fd;
+}
+/** setup rectangles */
+static bool set_rects(struct copybit_context_t *dev,
+                      struct mdp_blit_req *e,
+                      const struct copybit_rect_t *dst,
+                      const struct copybit_rect_t *src,
+                      const struct copybit_rect_t *scissor) {
+    struct copybit_rect_t clip;
+    intersect(&clip, scissor, dst);
+
+    if (!validateCopybitRect(&clip))
+       return false;
+
+    e->dst_rect.x  = clip.l;
+    e->dst_rect.y  = clip.t;
+    e->dst_rect.w  = clip.r - clip.l;
+    e->dst_rect.h  = clip.b - clip.t;
+
+    uint32_t W, H, delta_x, delta_y;
+    if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+        delta_x = (clip.t - dst->t);
+        delta_y = (dst->r - clip.r);
+        e->src_rect.w = (clip.b - clip.t);
+        e->src_rect.h = (clip.r - clip.l);
+        W = dst->b - dst->t;
+        H = dst->r - dst->l;
+    } else {
+        delta_x  = (clip.l - dst->l);
+        delta_y  = (clip.t - dst->t);
+        e->src_rect.w  = (clip.r - clip.l);
+        e->src_rect.h  = (clip.b - clip.t);
+        W = dst->r - dst->l;
+        H = dst->b - dst->t;
+    }
+
+    MULDIV(&delta_x, &e->src_rect.w, src->r - src->l, W);
+    MULDIV(&delta_y, &e->src_rect.h, src->b - src->t, H);
+
+    e->src_rect.x = delta_x + src->l;
+    e->src_rect.y = delta_y + src->t;
+
+    if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_V) {
+        if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+            e->src_rect.x = (src->l + src->r) - (e->src_rect.x + e->src_rect.w);
+        }else{
+            e->src_rect.y = (src->t + src->b) - (e->src_rect.y + e->src_rect.h);
+        }
+    }
+
+    if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_H) {
+        if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+            e->src_rect.y = (src->t + src->b) - (e->src_rect.y + e->src_rect.h);
+        }else{
+            e->src_rect.x = (src->l + src->r) - (e->src_rect.x + e->src_rect.w);
+        }
+    }
+    return true;
+}
+
+/** setup mdp request */
+static void set_infos(struct copybit_context_t *dev,
+                      struct mdp_blit_req *req, int flags)
+{
+    req->alpha = dev->mAlpha;
+    req->fps = dev->dynamic_fps;
+    req->transp_mask = MDP_TRANSP_NOP;
+    req->flags = dev->mFlags | flags;
+    // check if we are blitting to f/b
+    if (COPYBIT_ENABLE == dev->mBlitToFB) {
+        req->flags |= MDP_MEMORY_ID_TYPE_FB;
+    }
+#if defined(COPYBIT_QSD8K)
+    req->flags |= MDP_BLEND_FG_PREMULT;
+#endif
+}
+
+/** copy the bits */
+static int msm_copybit(struct copybit_context_t *dev, void const *list)
+{
+    int err;
+    if (dev->relFence != -1) {
+        close(dev->relFence);
+        dev->relFence = -1;
+    }
+    err = ioctl(dev->mFD, MSMFB_ASYNC_BLIT,
+                    (struct mdp_async_blit_req_list const*)list);
+    ALOGE_IF(err<0, "copyBits failed (%s)", strerror(errno));
+    if (err == 0) {
+        return 0;
+    } else {
+#if DEBUG_MDP_ERRORS
+        struct mdp_async_blit_req_list const* l =
+            (struct mdp_async_blit_req_list const*)list;
+        for (unsigned int i=0 ; i<l->count ; i++) {
+            ALOGE("%d: src={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
+                  "    dst={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
+                  "    flags=%08x, fps=%d"
+                  ,
+                  i,
+                  l->req[i].src.width,
+                  l->req[i].src.height,
+                  l->req[i].src.format,
+                  l->req[i].src_rect.x,
+                  l->req[i].src_rect.y,
+                  l->req[i].src_rect.w,
+                  l->req[i].src_rect.h,
+                  l->req[i].dst.width,
+                  l->req[i].dst.height,
+                  l->req[i].dst.format,
+                  l->req[i].dst_rect.x,
+                  l->req[i].dst_rect.y,
+                  l->req[i].dst_rect.w,
+                  l->req[i].dst_rect.h,
+                  l->req[i].flags,
+                  l->req[i].fps
+                 );
+        }
+#endif
+        return -errno;
+    }
+}
+
+/*****************************************************************************/
+
+/** Set a parameter to value */
+static int set_parameter_copybit(
+    struct copybit_device_t *dev,
+    int name,
+    int value)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int status = 0;
+    if (ctx) {
+        switch(name) {
+            case COPYBIT_ROTATION_DEG:
+                switch (value) {
+                    case 0:
+                        ctx->mFlags &= ~0x7;
+                        break;
+                    case 90:
+                        ctx->mFlags &= ~0x7;
+                        ctx->mFlags |= MDP_ROT_90;
+                        break;
+                    case 180:
+                        ctx->mFlags &= ~0x7;
+                        ctx->mFlags |= MDP_ROT_180;
+                        break;
+                    case 270:
+                        ctx->mFlags &= ~0x7;
+                        ctx->mFlags |= MDP_ROT_270;
+                        break;
+                    default:
+                        ALOGE("Invalid value for COPYBIT_ROTATION_DEG");
+                        status = -EINVAL;
+                        break;
+                }
+                break;
+            case COPYBIT_PLANE_ALPHA:
+                if (value < 0)      value = MDP_ALPHA_NOP;
+                if (value >= 256)   value = 255;
+                ctx->mAlpha = (uint8_t)value;
+                break;
+            case COPYBIT_DYNAMIC_FPS:
+                ctx->dynamic_fps = (uint8_t)value;
+                break;
+            case COPYBIT_DITHER:
+                if (value == COPYBIT_ENABLE) {
+                    ctx->mFlags |= MDP_DITHER;
+                } else if (value == COPYBIT_DISABLE) {
+                    ctx->mFlags &= ~MDP_DITHER;
+                }
+                break;
+            case COPYBIT_BLUR:
+                if (value == COPYBIT_ENABLE) {
+                    ctx->mFlags |= MDP_BLUR;
+                } else if (value == COPYBIT_DISABLE) {
+                    ctx->mFlags &= ~MDP_BLUR;
+                }
+                break;
+            case COPYBIT_BLEND_MODE:
+                if(value == COPYBIT_BLENDING_PREMULT) {
+                    ctx->mFlags |= MDP_BLEND_FG_PREMULT;
+                } else {
+                    ctx->mFlags &= ~MDP_BLEND_FG_PREMULT;
+                }
+                break;
+            case COPYBIT_TRANSFORM:
+                ctx->mFlags &= ~0x7;
+                ctx->mFlags |= value & 0x7;
+                break;
+            case COPYBIT_BLIT_TO_FRAMEBUFFER:
+                if (COPYBIT_ENABLE == value) {
+                    ctx->mBlitToFB = value;
+                } else if (COPYBIT_DISABLE == value) {
+                    ctx->mBlitToFB = value;
+                } else {
+                    ALOGE ("%s:Invalid input for COPYBIT_BLIT_TO_FRAMEBUFFER : %d",
+                            __FUNCTION__, value);
+                }
+                break;
+            case COPYBIT_FG_LAYER:
+                if(value == COPYBIT_ENABLE) {
+                     ctx->mFlags |= MDP_IS_FG;
+                } else if (value == COPYBIT_DISABLE) {
+                    ctx->mFlags &= ~MDP_IS_FG;
+                }
+                break ;
+            default:
+                status = -EINVAL;
+                break;
+        }
+    } else {
+        status = -EINVAL;
+    }
+    return status;
+}
+
+/** Get a static info value */
+static int get(struct copybit_device_t *dev, int name)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int value;
+    if (ctx) {
+        switch(name) {
+            case COPYBIT_MINIFICATION_LIMIT:
+                value = MAX_SCALE_FACTOR;
+                break;
+            case COPYBIT_MAGNIFICATION_LIMIT:
+                value = MAX_SCALE_FACTOR;
+                break;
+            case COPYBIT_SCALING_FRAC_BITS:
+                value = 32;
+                break;
+            case COPYBIT_ROTATION_STEP_DEG:
+                value = 90;
+                break;
+            default:
+                value = -EINVAL;
+        }
+    } else {
+        value = -EINVAL;
+    }
+    return value;
+}
+
+static int set_sync_copybit(struct copybit_device_t *dev,
+    int acquireFenceFd)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (acquireFenceFd != -1) {
+        if (ctx->list.sync.acq_fen_fd_cnt < (MDP_MAX_FENCE_FD - 1)) {
+            ctx->acqFence[ctx->list.sync.acq_fen_fd_cnt++] = acquireFenceFd;
+        } else {
+            int ret = -EINVAL;
+            struct blitReq *list = &ctx->list;
+
+            // Since fence is full kick off what is already in the list
+            ret = msm_copybit(ctx, list);
+            if (ret < 0) {
+                ALOGE("%s: Blit call failed", __FUNCTION__);
+                return -EINVAL;
+            }
+            list->count = 0;
+            list->sync.acq_fen_fd_cnt = 0;
+            ctx->acqFence[list->sync.acq_fen_fd_cnt++] = acquireFenceFd;
+        }
+    }
+    return 0;
+}
+
+/** do a stretch blit type operation */
+static int stretch_copybit(
+    struct copybit_device_t *dev,
+    struct copybit_image_t const *dst,
+    struct copybit_image_t const *src,
+    struct copybit_rect_t const *dst_rect,
+    struct copybit_rect_t const *src_rect,
+    struct copybit_region_t const *region)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    struct blitReq *list;
+    int status = 0;
+    private_handle_t *yv12_handle = NULL;
+
+    if (ctx) {
+        list = &ctx->list;
+
+        if (ctx->mAlpha < 255) {
+            switch (src->format) {
+                // we don't support plane alpha with RGBA formats
+                case HAL_PIXEL_FORMAT_RGBA_8888:
+                case HAL_PIXEL_FORMAT_BGRA_8888:
+                case HAL_PIXEL_FORMAT_RGBA_5551:
+                case HAL_PIXEL_FORMAT_RGBA_4444:
+                    ALOGE ("%s : Unsupported Pixel format %d", __FUNCTION__,
+                           src->format);
+                    return -EINVAL;
+            }
+        }
+
+        if (src_rect->l < 0 || (uint32_t)src_rect->r > src->w ||
+            src_rect->t < 0 || (uint32_t)src_rect->b > src->h) {
+            // this is always invalid
+            ALOGE ("%s : Invalid source rectangle : src_rect l %d t %d r %d b %d",\
+                   __FUNCTION__, src_rect->l, src_rect->t, src_rect->r, src_rect->b);
+
+            return -EINVAL;
+        }
+
+        if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
+            ALOGE ("%s : Invalid source dimensions w %d h %d", __FUNCTION__, src->w, src->h);
+            return -EINVAL;
+        }
+
+        if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
+            ALOGE ("%s : Invalid DST dimensions w %d h %d", __FUNCTION__, dst->w, dst->h);
+            return -EINVAL;
+        }
+
+        if(src->format ==  HAL_PIXEL_FORMAT_YV12) {
+            int usage =
+            GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED;
+            if (0 == alloc_buffer(&yv12_handle,src->w,src->h,
+                                  src->format, usage)){
+                if(0 == convertYV12toYCrCb420SP(src,yv12_handle)){
+                    (const_cast<copybit_image_t *>(src))->format =
+                        HAL_PIXEL_FORMAT_YCrCb_420_SP;
+                    (const_cast<copybit_image_t *>(src))->handle =
+                        yv12_handle;
+                    (const_cast<copybit_image_t *>(src))->base =
+                        (void *)yv12_handle->base;
+                }
+                else{
+                    ALOGE("Error copybit conversion from yv12 failed");
+                    if(yv12_handle)
+                        free_buffer(yv12_handle);
+                    return -EINVAL;
+                }
+            }
+            else{
+                ALOGE("Error:unable to allocate memeory for yv12 software conversion");
+                return -EINVAL;
+            }
+        }
+        const uint32_t maxCount =
+                (uint32_t)(sizeof(list->req)/sizeof(list->req[0]));
+        const struct copybit_rect_t bounds = { 0, 0, (int)dst->w, (int)dst->h };
+        struct copybit_rect_t clip;
+        status = 0;
+        while ((status == 0) && region->next(region, &clip)) {
+            intersect(&clip, &bounds, &clip);
+            mdp_blit_req* req = &list->req[list->count];
+            int flags = 0;
+
+            private_handle_t* src_hnd = (private_handle_t*)src->handle;
+            if(src_hnd != NULL &&
+                (!(src_hnd->flags & private_handle_t::PRIV_FLAGS_CACHED))) {
+                flags |=  MDP_BLIT_NON_CACHED;
+            }
+
+            // Set Color Space for MDP to configure CSC matrix
+            req->color_space = ITU_R_601;
+            MetaData_t *metadata = NULL;
+
+            if (src_hnd != NULL)
+                metadata = (MetaData_t *)src_hnd->base_metadata;
+
+            if (metadata && (metadata->operation & UPDATE_COLOR_SPACE)) {
+                req->color_space = metadata->colorSpace;
+            }
+
+            set_infos(ctx, req, flags);
+            set_image(&req->dst, dst);
+            set_image(&req->src, src);
+            if (set_rects(ctx, req, dst_rect, src_rect, &clip) == false)
+                continue;
+
+            if (req->src_rect.w<=0 || req->src_rect.h<=0)
+                continue;
+
+            if (req->dst_rect.w<=0 || req->dst_rect.h<=0)
+                continue;
+
+            if (++list->count == maxCount) {
+                status = msm_copybit(ctx, list);
+                list->sync.acq_fen_fd_cnt = 0;
+                list->count = 0;
+            }
+        }
+        if(yv12_handle) {
+            //Before freeing the buffer we need buffer passed through blit call
+            if (list->count != 0) {
+                status = msm_copybit(ctx, list);
+                list->sync.acq_fen_fd_cnt = 0;
+                list->count = 0;
+            }
+            free_buffer(yv12_handle);
+        }
+    } else {
+        ALOGE ("%s : Invalid COPYBIT context", __FUNCTION__);
+        status = -EINVAL;
+    }
+    return status;
+}
+
+/** Perform a blit type operation */
+static int blit_copybit(
+    struct copybit_device_t *dev,
+    struct copybit_image_t const *dst,
+    struct copybit_image_t const *src,
+    struct copybit_region_t const *region)
+{
+    struct copybit_rect_t dr = { 0, 0, (int)dst->w, (int)dst->h };
+    struct copybit_rect_t sr = { 0, 0, (int)src->w, (int)src->h };
+    return stretch_copybit(dev, dst, src, &dr, &sr, region);
+}
+
+static int finish_copybit(struct copybit_device_t *dev)
+{
+    // NOP for MDP copybit
+    if(!dev)
+       return -EINVAL;
+
+    return 0;
+}
+static int clear_copybit(struct copybit_device_t *dev,
+                         struct copybit_image_t const *buf,
+                         struct copybit_rect_t *rect)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    uint32_t color = 0; // black color
+
+    if (!ctx) {
+        ALOGE ("%s: Invalid copybit context", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    struct blitReq list1;
+    memset((char *)&list1 , 0 ,sizeof (struct blitReq) );
+    list1.count = 1;
+    int my_tmp_get_fence = -1;
+
+    list1.sync.acq_fen_fd  =  ctx->acqFence;
+    list1.sync.rel_fen_fd  =  &my_tmp_get_fence;
+    list1.sync.acq_fen_fd_cnt = ctx->list.sync.acq_fen_fd_cnt;
+    mdp_blit_req* req = &list1.req[0];
+
+    if(!req) {
+        ALOGE ("%s : Invalid request", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    set_image(&req->dst, buf);
+    set_image(&req->src, buf);
+
+    if (rect->l < 0 || (uint32_t)(rect->r - rect->l) > req->dst.width ||
+       rect->t < 0 || (uint32_t)(rect->b - rect->t) > req->dst.height) {
+       ALOGE ("%s : Invalid rect : src_rect l %d t %d r %d b %d",\
+       __FUNCTION__, rect->l, rect->t, rect->r, rect->b);
+       return -EINVAL;
+    }
+
+    req->dst_rect.x  = rect->l;
+    req->dst_rect.y  = rect->t;
+    req->dst_rect.w  = rect->r - rect->l;
+    req->dst_rect.h  = rect->b - rect->t;
+
+    req->src_rect = req->dst_rect;
+
+    req->const_color.b = (uint32_t)((color >> 16) & 0xff);
+    req->const_color.g = (uint32_t)((color >> 8) & 0xff);
+    req->const_color.r = (uint32_t)((color >> 0) & 0xff);
+    req->const_color.alpha = MDP_ALPHA_NOP;
+
+    req->transp_mask = MDP_TRANSP_NOP;
+    req->flags = MDP_SOLID_FILL | MDP_MEMORY_ID_TYPE_FB | MDP_BLEND_FG_PREMULT;
+    int status = msm_copybit(ctx, &list1);
+
+    ctx->list.sync.acq_fen_fd_cnt = 0;
+    if (my_tmp_get_fence !=  -1)
+        close(my_tmp_get_fence);
+
+    return status;
+}
+
+/** Fill the rect on dst with RGBA color **/
+static int fill_color(struct copybit_device_t *dev,
+                      struct copybit_image_t const *dst,
+                      struct copybit_rect_t const *rect,
+                      uint32_t color)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (!ctx) {
+        ALOGE("%s: Invalid copybit context", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
+        ALOGE("%s: Invalid DST w=%d h=%d", __FUNCTION__, dst->w, dst->h);
+        return -EINVAL;
+    }
+
+    if (rect->l < 0 || (uint32_t)(rect->r - rect->l) > dst->w ||
+        rect->t < 0 || (uint32_t)(rect->b - rect->t) > dst->h) {
+        ALOGE("%s: Invalid destination rect: l=%d t=%d r=%d b=%d",
+                __FUNCTION__, rect->l, rect->t, rect->r, rect->b);
+        return -EINVAL;
+    }
+
+    int status = 0;
+    struct blitReq* list = &ctx->list;
+    mdp_blit_req* req = &list->req[list->count++];
+    set_infos(ctx, req, MDP_SOLID_FILL);
+    set_image(&req->src, dst);
+    set_image(&req->dst, dst);
+
+    req->dst_rect.x = rect->l;
+    req->dst_rect.y = rect->t;
+    req->dst_rect.w = rect->r - rect->l;
+    req->dst_rect.h = rect->b - rect->t;
+    req->src_rect = req->dst_rect;
+
+    req->const_color.r = (uint32_t)((color >> 0) & 0xff);
+    req->const_color.g = (uint32_t)((color >> 8) & 0xff);
+    req->const_color.b = (uint32_t)((color >> 16) & 0xff);
+    req->const_color.alpha = (uint32_t)((color >> 24) & 0xff);
+
+    if (list->count == sizeof(list->req)/sizeof(list->req[0])) {
+        status = msm_copybit(ctx, list);
+        list->sync.acq_fen_fd_cnt = 0;
+        list->count = 0;
+    }
+    return status;
+}
+
+/*****************************************************************************/
+
+/** Close the copybit device */
+static int close_copybit(struct hw_device_t *dev)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (ctx) {
+        close(ctx->mFD);
+        free(ctx);
+    }
+    return 0;
+}
+
+static int flush_get_fence(struct copybit_device_t *dev, int* fd)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    struct blitReq *list = &ctx->list;
+    int ret = -EINVAL;
+
+    if (list->count) {
+        ret = msm_copybit(ctx, list);
+        if (ret < 0)
+            ALOGE("%s: Blit call failed", __FUNCTION__);
+        list->count = 0;
+    }
+    *fd = ctx->relFence;
+    list->sync.acq_fen_fd_cnt = 0;
+    ctx->relFence = -1;
+    return ret;
+}
+
+/** Open a new instance of a copybit device using name */
+static int open_copybit(const struct hw_module_t* module, const char* name,
+                        struct hw_device_t** device)
+{
+    int status = -EINVAL;
+
+    if (strcmp(name, COPYBIT_HARDWARE_COPYBIT0)) {
+        return COPYBIT_FAILURE;
+    }
+    copybit_context_t *ctx;
+    ctx = (copybit_context_t *)malloc(sizeof(copybit_context_t));
+
+    if (ctx == NULL ) {
+       return COPYBIT_FAILURE;
+    }
+
+    memset(ctx, 0, sizeof(*ctx));
+
+    ctx->device.common.tag = HARDWARE_DEVICE_TAG;
+    ctx->device.common.version = 1;
+    ctx->device.common.module = const_cast<hw_module_t*>(module);
+    ctx->device.common.close = close_copybit;
+    ctx->device.set_parameter = set_parameter_copybit;
+    ctx->device.get = get;
+    ctx->device.blit = blit_copybit;
+    ctx->device.set_sync = set_sync_copybit;
+    ctx->device.stretch = stretch_copybit;
+    ctx->device.finish = finish_copybit;
+    ctx->device.fill_color = fill_color;
+    ctx->device.flush_get_fence = flush_get_fence;
+    ctx->device.clear = clear_copybit;
+    ctx->mAlpha = MDP_ALPHA_NOP;
+    //dynamic_fps is zero means default
+    //panel refresh rate for driver.
+    ctx->dynamic_fps = 0;
+    ctx->mFlags = 0;
+    ctx->sync.flags = 0;
+    ctx->relFence = -1;
+    for (int i=0; i < MDP_MAX_FENCE_FD; i++) {
+        ctx->acqFence[i] = -1;
+    }
+    ctx->sync.acq_fen_fd = ctx->acqFence;
+    ctx->sync.rel_fen_fd = &ctx->relFence;
+    ctx->list.count = 0;
+    ctx->list.sync.acq_fen_fd_cnt = 0;
+    ctx->list.sync.rel_fen_fd = ctx->sync.rel_fen_fd;
+    ctx->list.sync.acq_fen_fd = ctx->sync.acq_fen_fd;
+    ctx->mFD = open("/dev/graphics/fb0", O_RDWR, 0);
+    if (ctx->mFD < 0) {
+        status = errno;
+        ALOGE("Error opening frame buffer errno=%d (%s)",
+              status, strerror(status));
+        status = -status;
+    } else {
+        status = 0;
+        *device = &ctx->device.common;
+    }
+    return status;
+}
diff --git a/sdm845/libcopybit/copybit.h b/sdm845/libcopybit/copybit.h
new file mode 100644
index 0000000..de585ee
--- /dev/null
+++ b/sdm845/libcopybit/copybit.h
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_COPYBIT_INTERFACE_H
+#define ANDROID_COPYBIT_INTERFACE_H
+
+#include <hardware/hardware.h>
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <gralloc_priv.h>
+
+__BEGIN_DECLS
+
+/**
+ * The id of this module
+ */
+#define COPYBIT_HARDWARE_MODULE_ID "copybit"
+
+/**
+ * Name of the graphics device to open
+ */
+#define COPYBIT_HARDWARE_COPYBIT0 "copybit0"
+
+/* supported pixel-formats. these must be compatible with
+ * graphics/PixelFormat.java, ui/PixelFormat.h, pixelflinger/format.h
+ */
+enum {
+    COPYBIT_FORMAT_RGBA_8888    = HAL_PIXEL_FORMAT_RGBA_8888,
+    COPYBIT_FORMAT_RGBX_8888    = HAL_PIXEL_FORMAT_RGBX_8888,
+    COPYBIT_FORMAT_RGB_888      = HAL_PIXEL_FORMAT_RGB_888,
+    COPYBIT_FORMAT_RGB_565      = HAL_PIXEL_FORMAT_RGB_565,
+    COPYBIT_FORMAT_BGRA_8888    = HAL_PIXEL_FORMAT_BGRA_8888,
+    COPYBIT_FORMAT_RGBA_5551    = HAL_PIXEL_FORMAT_RGBA_5551,
+    COPYBIT_FORMAT_RGBA_4444    = HAL_PIXEL_FORMAT_RGBA_4444,
+    COPYBIT_FORMAT_YCbCr_422_SP = 0x10,
+    COPYBIT_FORMAT_YCrCb_420_SP = 0x11,
+};
+
+/* name for copybit_set_parameter */
+enum {
+    /* Default blit destination is offline buffer */
+    /* clients to set this to '1', if blitting to framebuffer */
+    /* and reset to '0', after calling blit/stretch */
+    COPYBIT_BLIT_TO_FRAMEBUFFER = 0,
+    /* rotation of the source image in degrees (0 to 359) */
+    COPYBIT_ROTATION_DEG    = 1,
+    /* plane alpha value */
+    COPYBIT_PLANE_ALPHA     = 2,
+    /* enable or disable dithering */
+    COPYBIT_DITHER          = 3,
+    /* transformation applied (this is a superset of COPYBIT_ROTATION_DEG) */
+    COPYBIT_TRANSFORM       = 4,
+    /* blurs the copied bitmap. The amount of blurring cannot be changed
+     * at this time. */
+    COPYBIT_BLUR            = 5,
+    /* Blend mode */
+    COPYBIT_BLEND_MODE  = 6,
+    /* FB width */
+    COPYBIT_FRAMEBUFFER_WIDTH = 7,
+    /* FB height */
+    COPYBIT_FRAMEBUFFER_HEIGHT = 8,
+    COPYBIT_FG_LAYER = 9,
+    COPYBIT_DYNAMIC_FPS = 10,
+    /* Source Format Mode */
+    COPYBIT_SRC_FORMAT_MODE = 11,
+    /* Destination Format Mode */
+    COPYBIT_DST_FORMAT_MODE = 12,
+};
+
+/* values for copybit_set_parameter(COPYBIT_TRANSFORM) */
+enum {
+    /* flip source image horizontally */
+    COPYBIT_TRANSFORM_FLIP_H    = HAL_TRANSFORM_FLIP_H,
+    /* flip source image vertically */
+    COPYBIT_TRANSFORM_FLIP_V    = HAL_TRANSFORM_FLIP_V,
+    /* rotate source image 90 degres */
+    COPYBIT_TRANSFORM_ROT_90    = HAL_TRANSFORM_ROT_90,
+    /* rotate source image 180 degres */
+    COPYBIT_TRANSFORM_ROT_180   = HAL_TRANSFORM_ROT_180,
+    /* rotate source image 270 degres */
+    COPYBIT_TRANSFORM_ROT_270   = HAL_TRANSFORM_ROT_270,
+};
+
+/* enable/disable value copybit_set_parameter */
+enum {
+    COPYBIT_DISABLE = 0,
+    COPYBIT_ENABLE  = 1
+};
+
+/*
+ * copybit blending values. same as HWC blending values
+ */
+enum {
+    /* no blending */
+    COPYBIT_BLENDING_NONE     = 0x0100,
+
+    /* ONE / ONE_MINUS_SRC_ALPHA */
+    COPYBIT_BLENDING_PREMULT  = 0x0105,
+
+    /* SRC_ALPHA / ONE_MINUS_SRC_ALPHA */
+    COPYBIT_BLENDING_COVERAGE = 0x0405
+};
+
+enum {
+    /* Linear format mode*/
+    COPYBIT_LINEAR = 0x0000,
+    /* UBWC format mode*/
+    COPYBIT_UBWC_COMPRESSED = 0x0001,
+};
+
+/* use get_static_info() to query static informations about the hardware */
+enum {
+    /* Maximum amount of minification supported by the hardware*/
+    COPYBIT_MINIFICATION_LIMIT  = 1,
+    /* Maximum amount of magnification supported by the hardware */
+    COPYBIT_MAGNIFICATION_LIMIT = 2,
+    /* Number of fractional bits support by the scaling engine */
+    COPYBIT_SCALING_FRAC_BITS   = 3,
+    /* Supported rotation step in degres. */
+    COPYBIT_ROTATION_STEP_DEG   = 4,
+    /* UBWC support*/
+    COPYBIT_UBWC_SUPPORT        = 5,
+};
+
+/* Image structure */
+struct copybit_image_t {
+    /* width */
+    uint32_t    w;
+    /* height */
+    uint32_t    h;
+    /* format COPYBIT_FORMAT_xxx */
+    int32_t     format;
+    /* base of buffer with image */
+    void        *base;
+    /* handle to the image */
+    native_handle_t* handle;
+    /* number of pixels added for the stride */
+    uint32_t    horiz_padding;
+    /* number of pixels added for the vertical stride */
+    uint32_t    vert_padding;
+};
+
+/* Rectangle */
+struct copybit_rect_t {
+    /* left */
+    int l;
+    /* top */
+    int t;
+    /* right */
+    int r;
+    /* bottom */
+    int b;
+};
+
+/* Region */
+struct copybit_region_t {
+    int (*next)(struct copybit_region_t const *region, struct copybit_rect_t *rect);
+};
+
+/**
+ * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
+ * and the fields of this data structure must begin with hw_module_t
+ * followed by module specific information.
+ */
+struct copybit_module_t {
+    struct hw_module_t common;
+};
+
+/**
+ * Every device data structure must begin with hw_device_t
+ * followed by module specific public methods and attributes.
+ */
+struct copybit_device_t {
+    struct hw_device_t common;
+
+    /**
+     * Set a copybit parameter.
+     *
+     * @param dev from open
+     * @param name one for the COPYBIT_NAME_xxx
+     * @param value one of the COPYBIT_VALUE_xxx
+     *
+     * @return 0 if successful
+     */
+    int (*set_parameter)(struct copybit_device_t *dev, int name, int value);
+
+    /**
+     * Get a static copybit information.
+     *
+     * @param dev from open
+     * @param name one of the COPYBIT_STATIC_xxx
+     *
+     * @return value or -EINVAL if error
+     */
+    int (*get)(struct copybit_device_t *dev, int name);
+
+    /**
+     * Execute the bit blit copy operation
+     *
+     * @param dev from open
+     * @param dst is the destination image
+     * @param src is the source image
+     * @param region the clip region
+     *
+     * @return 0 if successful
+     */
+    int (*blit)(struct copybit_device_t *dev,
+                struct copybit_image_t const *dst,
+                struct copybit_image_t const *src,
+                struct copybit_region_t const *region);
+
+    /**
+     * Give acquire fence to copybit to be used in upcoming stretch
+     * call
+     *
+     * @param dev from open
+     * @param acquireFenceFd is the acquire fence
+     *
+     * @return 0 if successful
+     */
+    int (*set_sync)(struct copybit_device_t *dev,
+                   int acquireFenceFd);
+
+    /**
+     * Execute the stretch bit blit copy operation
+     *
+     * @param dev from open
+     * @param dst is the destination image
+     * @param src is the source image
+     * @param dst_rect is the destination rectangle
+     * @param src_rect is the source rectangle
+     * @param region the clip region
+     *
+     * @return 0 if successful
+     */
+    int (*stretch)(struct copybit_device_t *dev,
+                   struct copybit_image_t const *dst,
+                   struct copybit_image_t const *src,
+                   struct copybit_rect_t const *dst_rect,
+                   struct copybit_rect_t const *src_rect,
+                   struct copybit_region_t const *region);
+
+    /**
+     * Fill the rect on dst with RGBA color
+     *
+     * @param dev from open
+     * @param dst is destination image
+     * @param rect is destination rectangle
+     * @param color is RGBA color to fill
+     *
+     * @return 0 if successful
+     */
+    int (*fill_color)(struct copybit_device_t *dev,
+                      struct copybit_image_t const *dst,
+                      struct copybit_rect_t const *rect,
+                      uint32_t color);
+
+  /**
+    * Execute the completion of the copybit draw operation.
+    *
+    * @param dev from open
+    *
+    * @return 0 if successful
+    */
+  int (*finish)(struct copybit_device_t *dev);
+
+  /**
+    * Trigger the copybit draw operation(async).
+    *
+    * @param dev from open
+    *
+    * @param fd - gets the fencefd
+    *
+    * @return 0 if successful
+    */
+  int (*flush_get_fence)(struct copybit_device_t *dev, int* fd);
+
+  /* Clears the buffer
+   */
+  int (*clear)(struct copybit_device_t *dev, struct copybit_image_t const *buf,
+               struct copybit_rect_t *rect);
+};
+
+
+/** convenience API for opening and closing a device */
+
+static inline int copybit_open(const struct hw_module_t* module,
+                               struct copybit_device_t** device) {
+    return module->methods->open(module,
+                                 COPYBIT_HARDWARE_COPYBIT0, (struct hw_device_t**)device);
+}
+
+static inline int copybit_close(struct copybit_device_t* device) {
+    return device->common.close(&device->common);
+}
+
+
+__END_DECLS
+
+#endif  // ANDROID_COPYBIT_INTERFACE_H
diff --git a/sdm845/libcopybit/copybit_c2d.cpp b/sdm845/libcopybit/copybit_c2d.cpp
new file mode 100644
index 0000000..240ba26
--- /dev/null
+++ b/sdm845/libcopybit/copybit_c2d.cpp
@@ -0,0 +1,1776 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <cutils/log.h>
+#include <sys/resource.h>
+#include <sys/prctl.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <linux/msm_kgsl.h>
+
+#include <EGL/eglplatform.h>
+#include <cutils/native_handle.h>
+
+#include <copybit.h>
+#include <alloc_controller.h>
+#include <memalloc.h>
+
+#include "c2d2.h"
+#include "software_converter.h"
+
+#include <dlfcn.h>
+
+using gralloc::IMemAlloc;
+using gralloc::IonController;
+using gralloc::alloc_data;
+
+C2D_STATUS (*LINK_c2dCreateSurface)( uint32 *surface_id,
+                                     uint32 surface_bits,
+                                     C2D_SURFACE_TYPE surface_type,
+                                     void *surface_definition );
+
+C2D_STATUS (*LINK_c2dUpdateSurface)( uint32 surface_id,
+                                     uint32 surface_bits,
+                                     C2D_SURFACE_TYPE surface_type,
+                                     void *surface_definition );
+
+C2D_STATUS (*LINK_c2dReadSurface)( uint32 surface_id,
+                                   C2D_SURFACE_TYPE surface_type,
+                                   void *surface_definition,
+                                   int32 x, int32 y );
+
+C2D_STATUS (*LINK_c2dDraw)( uint32 target_id,
+                            uint32 target_config, C2D_RECT *target_scissor,
+                            uint32 target_mask_id, uint32 target_color_key,
+                            C2D_OBJECT *objects_list, uint32 num_objects );
+
+C2D_STATUS (*LINK_c2dFinish)( uint32 target_id);
+
+C2D_STATUS (*LINK_c2dFlush)( uint32 target_id, c2d_ts_handle *timestamp);
+
+C2D_STATUS (*LINK_c2dWaitTimestamp)( c2d_ts_handle timestamp );
+
+C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id );
+
+C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, size_t len,
+                                size_t offset, uint32 flags, void ** gpuaddr);
+
+C2D_STATUS (*LINK_c2dUnMapAddr) ( void * gpuaddr);
+
+C2D_STATUS (*LINK_c2dGetDriverCapabilities) ( C2D_DRIVER_INFO * driver_info);
+
+/* create a fence fd for the timestamp */
+C2D_STATUS (*LINK_c2dCreateFenceFD) ( uint32 target_id, c2d_ts_handle timestamp,
+                                                            int32 *fd);
+
+C2D_STATUS (*LINK_c2dFillSurface) ( uint32 surface_id, uint32 fill_color,
+                                    C2D_RECT * fill_rect);
+
+/******************************************************************************/
+
+#if defined(COPYBIT_Z180)
+#define MAX_SCALE_FACTOR    (4096)
+#define MAX_DIMENSION       (4096)
+#else
+#error "Unsupported HW version"
+#endif
+
+// The following defines can be changed as required i.e. as we encounter
+// complex use cases.
+#define MAX_RGB_SURFACES 32       // Max. RGB layers currently supported per draw
+#define MAX_YUV_2_PLANE_SURFACES 4// Max. 2-plane YUV layers currently supported per draw
+#define MAX_YUV_3_PLANE_SURFACES 1// Max. 3-plane YUV layers currently supported per draw
+// +1 for the destination surface. We cannot have multiple destination surfaces.
+#define MAX_SURFACES (MAX_RGB_SURFACES + MAX_YUV_2_PLANE_SURFACES + MAX_YUV_3_PLANE_SURFACES + 1)
+#define NUM_SURFACE_TYPES 3      // RGB_SURFACE + YUV_SURFACE_2_PLANES + YUV_SURFACE_3_PLANES
+#define MAX_BLIT_OBJECT_COUNT 50 // Max. blit objects that can be passed per draw
+
+enum {
+    RGB_SURFACE,
+    YUV_SURFACE_2_PLANES,
+    YUV_SURFACE_3_PLANES
+};
+
+enum eConversionType {
+    CONVERT_TO_ANDROID_FORMAT,
+    CONVERT_TO_C2D_FORMAT
+};
+
+enum eC2DFlags {
+    FLAGS_PREMULTIPLIED_ALPHA  = 1<<0,
+    FLAGS_YUV_DESTINATION      = 1<<1,
+    FLAGS_TEMP_SRC_DST         = 1<<2,
+    FLAGS_UBWC_FORMAT_MODE     = 1<<3
+};
+
+static gralloc::IAllocController* sAlloc = 0;
+/******************************************************************************/
+
+/** State information for each device instance */
+struct copybit_context_t {
+    struct copybit_device_t device;
+    // Templates for the various source surfaces. These templates are created
+    // to avoid the expensive create/destroy C2D Surfaces
+    C2D_OBJECT_STR blit_rgb_object[MAX_RGB_SURFACES];
+    C2D_OBJECT_STR blit_yuv_2_plane_object[MAX_YUV_2_PLANE_SURFACES];
+    C2D_OBJECT_STR blit_yuv_3_plane_object[MAX_YUV_3_PLANE_SURFACES];
+    C2D_OBJECT_STR blit_list[MAX_BLIT_OBJECT_COUNT]; // Z-ordered list of blit objects
+    C2D_DRIVER_INFO c2d_driver_info;
+    void *libc2d2;
+    alloc_data temp_src_buffer;
+    alloc_data temp_dst_buffer;
+    unsigned int dst[NUM_SURFACE_TYPES]; // dst surfaces
+    uintptr_t mapped_gpu_addr[MAX_SURFACES]; // GPU addresses mapped inside copybit
+    int blit_rgb_count;         // Total RGB surfaces being blit
+    int blit_yuv_2_plane_count; // Total 2 plane YUV surfaces being
+    int blit_yuv_3_plane_count; // Total 3 plane YUV  surfaces being blit
+    int blit_count;             // Total blit objects.
+    unsigned int trg_transform;      /* target transform */
+    int fb_width;
+    int fb_height;
+    int src_global_alpha;
+    int config_mask;
+    int dst_surface_type;
+    bool is_premultiplied_alpha;
+    void* time_stamp;
+    bool dst_surface_mapped; // Set when dst surface is mapped to GPU addr
+    void* dst_surface_base; // Stores the dst surface addr
+    bool is_src_ubwc_format;
+    bool is_dst_ubwc_format;
+
+    // used for signaling the wait thread
+    bool wait_timestamp;
+    pthread_t wait_thread_id;
+    bool stop_thread;
+    pthread_mutex_t wait_cleanup_lock;
+    pthread_cond_t wait_cleanup_cond;
+
+};
+
+struct bufferInfo {
+    int width;
+    int height;
+    int format;
+};
+
+struct yuvPlaneInfo {
+    int yStride;       //luma stride
+    int plane1_stride;
+    int plane2_stride;
+    size_t plane1_offset;
+    size_t plane2_offset;
+};
+
+/**
+ * Common hardware methods
+ */
+
+static int open_copybit(const struct hw_module_t* module, const char* name,
+                        struct hw_device_t** device);
+
+static struct hw_module_methods_t copybit_module_methods = {
+    .open = open_copybit,
+};
+
+/*
+ * The COPYBIT Module
+ */
+struct copybit_module_t HAL_MODULE_INFO_SYM = {
+    .common = {
+        .tag =  HARDWARE_MODULE_TAG,
+        .version_major = 1,
+        .version_minor = 0,
+        .id = COPYBIT_HARDWARE_MODULE_ID,
+        .name = "QCT COPYBIT C2D 2.0 Module",
+        .author = "Qualcomm",
+        .methods =  &copybit_module_methods
+    }
+};
+
+
+/* thread function which waits on the timeStamp and cleans up the surfaces */
+static void* c2d_wait_loop(void* ptr) {
+    copybit_context_t* ctx = (copybit_context_t*)(ptr);
+    char thread_name[64] = "copybitWaitThr";
+    prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
+    setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+
+    while(ctx->stop_thread == false) {
+        pthread_mutex_lock(&ctx->wait_cleanup_lock);
+        while(ctx->wait_timestamp == false && !ctx->stop_thread) {
+            pthread_cond_wait(&(ctx->wait_cleanup_cond),
+                              &(ctx->wait_cleanup_lock));
+        }
+        if(ctx->wait_timestamp) {
+            if(LINK_c2dWaitTimestamp(ctx->time_stamp)) {
+                ALOGE("%s: LINK_c2dWaitTimeStamp ERROR!!", __FUNCTION__);
+            }
+            ctx->wait_timestamp = false;
+            // Unmap any mapped addresses.
+            for (int i = 0; i < MAX_SURFACES; i++) {
+                if (ctx->mapped_gpu_addr[i]) {
+                    LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]);
+                    ctx->mapped_gpu_addr[i] = 0;
+                }
+            }
+            // Reset the counts after the draw.
+            ctx->blit_rgb_count = 0;
+            ctx->blit_yuv_2_plane_count = 0;
+            ctx->blit_yuv_3_plane_count = 0;
+            ctx->blit_count = 0;
+            ctx->dst_surface_mapped = false;
+            ctx->dst_surface_base = 0;
+        }
+        pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+        if(ctx->stop_thread)
+            break;
+    }
+    pthread_exit(NULL);
+    return NULL;
+}
+
+
+/* convert COPYBIT_FORMAT to C2D format */
+static int get_format(int format) {
+    switch (format) {
+        case HAL_PIXEL_FORMAT_RGB_565:        return C2D_COLOR_FORMAT_565_RGB;
+        case HAL_PIXEL_FORMAT_RGB_888:        return C2D_COLOR_FORMAT_888_RGB |
+                                              C2D_FORMAT_SWAP_RB;
+        case HAL_PIXEL_FORMAT_RGBX_8888:      return C2D_COLOR_FORMAT_8888_ARGB |
+                                              C2D_FORMAT_SWAP_RB |
+                                                  C2D_FORMAT_DISABLE_ALPHA;
+        case HAL_PIXEL_FORMAT_RGBA_8888:      return C2D_COLOR_FORMAT_8888_ARGB |
+                                              C2D_FORMAT_SWAP_RB;
+        case HAL_PIXEL_FORMAT_BGRA_8888:      return C2D_COLOR_FORMAT_8888_ARGB;
+        case HAL_PIXEL_FORMAT_RGBA_5551:      return C2D_COLOR_FORMAT_5551_RGBA;
+        case HAL_PIXEL_FORMAT_RGBA_4444:      return C2D_COLOR_FORMAT_4444_RGBA;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:   return C2D_COLOR_FORMAT_420_NV12;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV12;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:   return C2D_COLOR_FORMAT_420_NV21;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return C2D_COLOR_FORMAT_420_NV12 |
+                                                  C2D_FORMAT_MACROTILED;
+        default:                              ALOGE("%s: invalid format (0x%x",
+                                                     __FUNCTION__, format);
+                                              return -EINVAL;
+    }
+    return -EINVAL;
+}
+
+/* Get the C2D formats needed for conversion to YUV */
+static int get_c2d_format_for_yuv_destination(int halFormat) {
+    switch (halFormat) {
+        // We do not swap the RB when the target is YUV
+        case HAL_PIXEL_FORMAT_RGBX_8888:      return C2D_COLOR_FORMAT_8888_ARGB |
+                                              C2D_FORMAT_DISABLE_ALPHA;
+        case HAL_PIXEL_FORMAT_RGBA_8888:      return C2D_COLOR_FORMAT_8888_ARGB;
+        // The U and V need to be interchanged when the target is YUV
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:   return C2D_COLOR_FORMAT_420_NV21;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV21;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:   return C2D_COLOR_FORMAT_420_NV12;
+        default:                              return get_format(halFormat);
+    }
+    return -EINVAL;
+}
+
+/* ------------------------------------------------------------------- *//*!
+ * \internal
+ * \brief Get the bpp for a particular color format
+ * \param color format
+ * \return bits per pixel
+ *//* ------------------------------------------------------------------- */
+int c2diGetBpp(int32 colorformat)
+{
+
+    int c2dBpp = 0;
+
+    switch(colorformat&0xFF)
+    {
+        case C2D_COLOR_FORMAT_4444_RGBA:
+        case C2D_COLOR_FORMAT_4444_ARGB:
+        case C2D_COLOR_FORMAT_1555_ARGB:
+        case C2D_COLOR_FORMAT_565_RGB:
+        case C2D_COLOR_FORMAT_5551_RGBA:
+            c2dBpp = 16;
+            break;
+        case C2D_COLOR_FORMAT_8888_RGBA:
+        case C2D_COLOR_FORMAT_8888_ARGB:
+            c2dBpp = 32;
+            break;
+        case C2D_COLOR_FORMAT_888_RGB:
+            c2dBpp = 24;
+            break;
+        case C2D_COLOR_FORMAT_8_L:
+        case C2D_COLOR_FORMAT_8_A:
+            c2dBpp = 8;
+            break;
+        case C2D_COLOR_FORMAT_4_A:
+            c2dBpp = 4;
+            break;
+        case C2D_COLOR_FORMAT_1:
+            c2dBpp = 1;
+            break;
+        default:
+            ALOGE("%s ERROR", __func__);
+            break;
+    }
+    return c2dBpp;
+}
+
+static size_t c2d_get_gpuaddr(copybit_context_t* ctx,
+                              struct private_handle_t *handle, int &mapped_idx)
+{
+    uint32 memtype;
+    size_t *gpuaddr = 0;
+    C2D_STATUS rc;
+    int freeindex = 0;
+    bool mapaddr = false;
+
+    if(!handle)
+        return 0;
+
+    if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ION)
+        memtype = KGSL_USER_MEM_TYPE_ION;
+    else {
+        ALOGE("Invalid handle flags: 0x%x", handle->flags);
+        return 0;
+    }
+
+    // Check for a freeindex in the mapped_gpu_addr list
+    for (freeindex = 0; freeindex < MAX_SURFACES; freeindex++) {
+        if (ctx->mapped_gpu_addr[freeindex] == 0) {
+            // free index is available
+            // map GPU addr and use this as mapped_idx
+            mapaddr = true;
+            break;
+        }
+    }
+
+    if(mapaddr) {
+        rc = LINK_c2dMapAddr(handle->fd, (void*)handle->base, handle->size,
+                             handle->offset, memtype, (void**)&gpuaddr);
+
+        if (rc == C2D_STATUS_OK) {
+            // We have mapped the GPU address inside copybit. We need to unmap
+            // this address after the blit. Store this address
+            ctx->mapped_gpu_addr[freeindex] = (size_t)gpuaddr;
+            mapped_idx = freeindex;
+        }
+    }
+    return (size_t)gpuaddr;
+}
+
+static void unmap_gpuaddr(copybit_context_t* ctx, int mapped_idx)
+{
+    if (!ctx || (mapped_idx == -1))
+        return;
+
+    if (ctx->mapped_gpu_addr[mapped_idx]) {
+        LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[mapped_idx]);
+        ctx->mapped_gpu_addr[mapped_idx] = 0;
+    }
+}
+
+static int is_supported_rgb_format(int format)
+{
+    switch(format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGB_888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444: {
+            return COPYBIT_SUCCESS;
+        }
+        default:
+            return COPYBIT_FAILURE;
+    }
+}
+
+static int get_num_planes(int format)
+{
+    switch(format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
+            return 2;
+        }
+        case HAL_PIXEL_FORMAT_YV12: {
+            return 3;
+        }
+        default:
+            return COPYBIT_FAILURE;
+    }
+}
+
+static int is_supported_yuv_format(int format)
+{
+    switch(format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
+            return COPYBIT_SUCCESS;
+        }
+        default:
+            return COPYBIT_FAILURE;
+    }
+}
+
+static int is_valid_destination_format(int format)
+{
+    if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
+        // C2D does not support NV12Tile as a destination format.
+        return COPYBIT_FAILURE;
+    }
+    return COPYBIT_SUCCESS;
+}
+
+static int calculate_yuv_offset_and_stride(const bufferInfo& info,
+                                           yuvPlaneInfo& yuvInfo)
+{
+    int width  = info.width;
+    int height = info.height;
+    int format = info.format;
+
+    int aligned_height = 0;
+    int aligned_width = 0, size = 0;
+
+    switch (format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
+            /* NV12 Tile buffers have their luma height aligned to 32bytes and width
+             * aligned to 128 bytes. The chroma offset starts at an 8K boundary
+             */
+            aligned_height = ALIGN(height, 32);
+            aligned_width  = ALIGN(width, 128);
+            size = aligned_width * aligned_height;
+            yuvInfo.plane1_offset = ALIGN(size,8192);
+            yuvInfo.yStride = aligned_width;
+            yuvInfo.plane1_stride = aligned_width;
+            break;
+        }
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
+            aligned_width = ALIGN(width, 32);
+            yuvInfo.yStride = aligned_width;
+            yuvInfo.plane1_stride = aligned_width;
+            if (HAL_PIXEL_FORMAT_NV12_ENCODEABLE == format) {
+                // The encoder requires a 2K aligned chroma offset
+                yuvInfo.plane1_offset = ALIGN(aligned_width * height, 2048);
+            } else
+                yuvInfo.plane1_offset = aligned_width * height;
+
+            break;
+        }
+        default: {
+            return COPYBIT_FAILURE;
+        }
+    }
+    return COPYBIT_SUCCESS;
+}
+
+/** create C2D surface from copybit image */
+static int set_image(copybit_context_t* ctx, uint32 surfaceId,
+                      const struct copybit_image_t *rhs,
+                      const eC2DFlags flags, int &mapped_idx)
+{
+    struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+    C2D_SURFACE_TYPE surfaceType;
+    int status = COPYBIT_SUCCESS;
+    uint64_t gpuaddr = 0;
+    int c2d_format;
+    mapped_idx = -1;
+
+    if (flags & FLAGS_YUV_DESTINATION) {
+        c2d_format = get_c2d_format_for_yuv_destination(rhs->format);
+    } else {
+        c2d_format = get_format(rhs->format);
+    }
+
+    if(c2d_format == -EINVAL) {
+        ALOGE("%s: invalid format", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    if(handle == NULL) {
+        ALOGE("%s: invalid handle", __func__);
+        return -EINVAL;
+    }
+
+    if (handle->gpuaddr == 0) {
+        gpuaddr = c2d_get_gpuaddr(ctx, handle, mapped_idx);
+        if(!gpuaddr) {
+            ALOGE("%s: c2d_get_gpuaddr failed", __FUNCTION__);
+            return COPYBIT_FAILURE;
+        }
+    } else {
+        gpuaddr = handle->gpuaddr;
+    }
+
+    /* create C2D surface */
+    if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
+        /* RGB */
+        C2D_RGB_SURFACE_DEF surfaceDef;
+
+        surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS);
+
+        surfaceDef.phys = (void*) gpuaddr;
+        surfaceDef.buffer = (void*) (handle->base);
+
+        surfaceDef.format = c2d_format |
+            ((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0);
+
+        surfaceDef.format = surfaceDef.format |
+            ((flags & FLAGS_UBWC_FORMAT_MODE) ? C2D_FORMAT_UBWC_COMPRESSED : 0);
+
+        surfaceDef.width = rhs->w;
+        surfaceDef.height = rhs->h;
+        int aligned_width = ALIGN((int)surfaceDef.width,32);
+        surfaceDef.stride = (aligned_width * c2diGetBpp(surfaceDef.format))>>3;
+
+        if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
+                                  &surfaceDef)) {
+            ALOGE("%s: RGB Surface c2dUpdateSurface ERROR", __FUNCTION__);
+            unmap_gpuaddr(ctx, mapped_idx);
+            status = COPYBIT_FAILURE;
+        }
+    } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
+        C2D_YUV_SURFACE_DEF surfaceDef;
+        memset(&surfaceDef, 0, sizeof(surfaceDef));
+        surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS);
+        surfaceDef.format = c2d_format;
+
+        bufferInfo info;
+        info.width = rhs->w;
+        info.height = rhs->h;
+        info.format = rhs->format;
+
+        yuvPlaneInfo yuvInfo = {0};
+        status = calculate_yuv_offset_and_stride(info, yuvInfo);
+        if(status != COPYBIT_SUCCESS) {
+            ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
+            unmap_gpuaddr(ctx, mapped_idx);
+        }
+
+        surfaceDef.width = rhs->w;
+        surfaceDef.height = rhs->h;
+        surfaceDef.plane0 = (void*) (handle->base);
+        surfaceDef.phys0 = (void*) (gpuaddr);
+        surfaceDef.stride0 = yuvInfo.yStride;
+
+        surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
+        surfaceDef.phys1 = (void*) (gpuaddr + yuvInfo.plane1_offset);
+        surfaceDef.stride1 = yuvInfo.plane1_stride;
+        if (3 == get_num_planes(rhs->format)) {
+            surfaceDef.plane2 = (void*) (handle->base + yuvInfo.plane2_offset);
+            surfaceDef.phys2 = (void*) (gpuaddr + yuvInfo.plane2_offset);
+            surfaceDef.stride2 = yuvInfo.plane2_stride;
+        }
+
+        if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
+                                  &surfaceDef)) {
+            ALOGE("%s: YUV Surface c2dUpdateSurface ERROR", __FUNCTION__);
+            unmap_gpuaddr(ctx, mapped_idx);
+            status = COPYBIT_FAILURE;
+        }
+    } else {
+        ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
+        unmap_gpuaddr(ctx, mapped_idx);
+        status = COPYBIT_FAILURE;
+    }
+
+    return status;
+}
+
+/** copy the bits */
+static int msm_copybit(struct copybit_context_t *ctx, unsigned int target)
+{
+    if (ctx->blit_count == 0) {
+        return COPYBIT_SUCCESS;
+    }
+
+    for (int i = 0; i < ctx->blit_count; i++)
+    {
+        ctx->blit_list[i].next = &(ctx->blit_list[i+1]);
+    }
+    ctx->blit_list[ctx->blit_count-1].next = NULL;
+    uint32_t target_transform = ctx->trg_transform;
+    if (ctx->c2d_driver_info.capabilities_mask &
+        C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) {
+        // For A3xx - set 0x0 as the transform is set in the config_mask
+        target_transform = 0x0;
+    }
+    if(LINK_c2dDraw(target, target_transform, 0x0, 0, 0, ctx->blit_list,
+                    ctx->blit_count)) {
+        ALOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+    return COPYBIT_SUCCESS;
+}
+
+
+
+static int flush_get_fence_copybit (struct copybit_device_t *dev, int* fd)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int status = COPYBIT_FAILURE;
+    if (!ctx)
+        return COPYBIT_FAILURE;
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
+
+    if(LINK_c2dFlush(ctx->dst[ctx->dst_surface_type], &ctx->time_stamp)) {
+        ALOGE("%s: LINK_c2dFlush ERROR", __FUNCTION__);
+        // unlock the mutex and return failure
+        pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+        return COPYBIT_FAILURE;
+    }
+    if(LINK_c2dCreateFenceFD(ctx->dst[ctx->dst_surface_type], ctx->time_stamp,
+                                                                        fd)) {
+        ALOGE("%s: LINK_c2dCreateFenceFD ERROR", __FUNCTION__);
+        status = COPYBIT_FAILURE;
+    }
+    if(status == COPYBIT_SUCCESS) {
+        //signal the wait_thread
+        ctx->wait_timestamp = true;
+        pthread_cond_signal(&ctx->wait_cleanup_cond);
+    }
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    return status;
+}
+
+static int finish_copybit(struct copybit_device_t *dev)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (!ctx)
+        return COPYBIT_FAILURE;
+
+   int status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
+
+   if(LINK_c2dFinish(ctx->dst[ctx->dst_surface_type])) {
+        ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    // Unmap any mapped addresses.
+    for (int i = 0; i < MAX_SURFACES; i++) {
+        if (ctx->mapped_gpu_addr[i]) {
+            LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]);
+            ctx->mapped_gpu_addr[i] = 0;
+        }
+    }
+
+    // Reset the counts after the draw.
+    ctx->blit_rgb_count = 0;
+    ctx->blit_yuv_2_plane_count = 0;
+    ctx->blit_yuv_3_plane_count = 0;
+    ctx->blit_count = 0;
+    ctx->dst_surface_mapped = false;
+    ctx->dst_surface_base = 0;
+
+    return status;
+}
+
+static int clear_copybit(struct copybit_device_t *dev,
+                         struct copybit_image_t const *buf,
+                         struct copybit_rect_t *rect)
+{
+    int ret = COPYBIT_SUCCESS;
+    int flags = FLAGS_PREMULTIPLIED_ALPHA;
+    int mapped_dst_idx = -1;
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (ctx->is_dst_ubwc_format)
+        flags |= FLAGS_UBWC_FORMAT_MODE;
+    C2D_RECT c2drect = {rect->l, rect->t, rect->r - rect->l, rect->b - rect->t};
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    if(!ctx->dst_surface_mapped) {
+        ret = set_image(ctx, ctx->dst[RGB_SURFACE], buf,
+                        (eC2DFlags)flags, mapped_dst_idx);
+        if(ret) {
+            ALOGE("%s: set_image error", __FUNCTION__);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
+            pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+            return COPYBIT_FAILURE;
+        }
+        //clear_copybit is the first call made by HWC for each composition
+        //with the dest surface, hence set dst_surface_mapped.
+        ctx->dst_surface_mapped = true;
+        ctx->dst_surface_base = buf->base;
+        ret = LINK_c2dFillSurface(ctx->dst[RGB_SURFACE], 0x0, &c2drect);
+    }
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    return ret;
+}
+
+
+/** setup rectangles */
+static void set_rects(struct copybit_context_t *ctx,
+                      C2D_OBJECT *c2dObject,
+                      const struct copybit_rect_t *dst,
+                      const struct copybit_rect_t *src,
+                      const struct copybit_rect_t *scissor)
+{
+    // Set the target rect.
+    if((ctx->trg_transform & C2D_TARGET_ROTATE_90) &&
+       (ctx->trg_transform & C2D_TARGET_ROTATE_180)) {
+        /* target rotation is 270 */
+        c2dObject->target_rect.x        = (dst->t)<<16;
+        c2dObject->target_rect.y        = ctx->fb_width?
+                (ALIGN(ctx->fb_width,32)- dst->r):dst->r;
+        c2dObject->target_rect.y        = c2dObject->target_rect.y<<16;
+        c2dObject->target_rect.height   = ((dst->r) - (dst->l))<<16;
+        c2dObject->target_rect.width    = ((dst->b) - (dst->t))<<16;
+    } else if(ctx->trg_transform & C2D_TARGET_ROTATE_90) {
+        c2dObject->target_rect.x        = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
+        c2dObject->target_rect.x        = c2dObject->target_rect.x<<16;
+        c2dObject->target_rect.y        = (dst->l)<<16;
+        c2dObject->target_rect.height   = ((dst->r) - (dst->l))<<16;
+        c2dObject->target_rect.width    = ((dst->b) - (dst->t))<<16;
+    } else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) {
+        c2dObject->target_rect.y        = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
+        c2dObject->target_rect.y        = c2dObject->target_rect.y<<16;
+        c2dObject->target_rect.x        = ctx->fb_width?
+                (ALIGN(ctx->fb_width,32) - dst->r):dst->r;
+        c2dObject->target_rect.x        = c2dObject->target_rect.x<<16;
+        c2dObject->target_rect.height   = ((dst->b) - (dst->t))<<16;
+        c2dObject->target_rect.width    = ((dst->r) - (dst->l))<<16;
+    } else {
+        c2dObject->target_rect.x        = (dst->l)<<16;
+        c2dObject->target_rect.y        = (dst->t)<<16;
+        c2dObject->target_rect.height   = ((dst->b) - (dst->t))<<16;
+        c2dObject->target_rect.width    = ((dst->r) - (dst->l))<<16;
+    }
+    c2dObject->config_mask |= C2D_TARGET_RECT_BIT;
+
+    // Set the source rect
+    c2dObject->source_rect.x        = (src->l)<<16;
+    c2dObject->source_rect.y        = (src->t)<<16;
+    c2dObject->source_rect.height   = ((src->b) - (src->t))<<16;
+    c2dObject->source_rect.width    = ((src->r) - (src->l))<<16;
+    c2dObject->config_mask |= C2D_SOURCE_RECT_BIT;
+
+    // Set the scissor rect
+    c2dObject->scissor_rect.x       = scissor->l;
+    c2dObject->scissor_rect.y       = scissor->t;
+    c2dObject->scissor_rect.height  = (scissor->b) - (scissor->t);
+    c2dObject->scissor_rect.width   = (scissor->r) - (scissor->l);
+    c2dObject->config_mask |= C2D_SCISSOR_RECT_BIT;
+}
+
+/*****************************************************************************/
+
+/** Set a parameter to value */
+static int set_parameter_copybit(
+    struct copybit_device_t *dev,
+    int name,
+    int value)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int status = COPYBIT_SUCCESS;
+    if (!ctx) {
+        ALOGE("%s: null context", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    switch(name) {
+        case COPYBIT_PLANE_ALPHA:
+        {
+            if (value < 0)      value = 0;
+            if (value >= 256)   value = 255;
+
+            ctx->src_global_alpha = value;
+            if (value < 255)
+                ctx->config_mask |= C2D_GLOBAL_ALPHA_BIT;
+            else
+                ctx->config_mask &= ~C2D_GLOBAL_ALPHA_BIT;
+        }
+        break;
+        case COPYBIT_BLEND_MODE:
+        {
+            if (value == COPYBIT_BLENDING_NONE) {
+                ctx->config_mask |= C2D_ALPHA_BLEND_NONE;
+                ctx->is_premultiplied_alpha = true;
+            } else if (value == COPYBIT_BLENDING_PREMULT) {
+                ctx->is_premultiplied_alpha = true;
+            } else {
+                ctx->config_mask &= ~C2D_ALPHA_BLEND_NONE;
+            }
+        }
+        break;
+        case COPYBIT_TRANSFORM:
+        {
+            unsigned int transform = 0;
+            uint32 config_mask = 0;
+            config_mask |= C2D_OVERRIDE_GLOBAL_TARGET_ROTATE_CONFIG;
+            if((value & 0x7) == COPYBIT_TRANSFORM_ROT_180) {
+                transform = C2D_TARGET_ROTATE_180;
+                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_180;
+            } else if((value & 0x7) == COPYBIT_TRANSFORM_ROT_270) {
+                transform = C2D_TARGET_ROTATE_90;
+                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_90;
+            } else if(value == COPYBIT_TRANSFORM_ROT_90) {
+                transform = C2D_TARGET_ROTATE_270;
+                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_270;
+            } else {
+                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_0;
+                if(value & COPYBIT_TRANSFORM_FLIP_H) {
+                    config_mask |= C2D_MIRROR_H_BIT;
+                } else if(value & COPYBIT_TRANSFORM_FLIP_V) {
+                    config_mask |= C2D_MIRROR_V_BIT;
+                }
+            }
+
+            if (ctx->c2d_driver_info.capabilities_mask &
+                C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) {
+                ctx->config_mask |= config_mask;
+            } else {
+                // The transform for this surface does not match the current
+                // target transform. Draw all previous surfaces. This will be
+                // changed once we have a new mechanism to send different
+                // target rotations to c2d.
+                finish_copybit(dev);
+            }
+            ctx->trg_transform = transform;
+        }
+        break;
+        case COPYBIT_FRAMEBUFFER_WIDTH:
+            ctx->fb_width = value;
+            break;
+        case COPYBIT_FRAMEBUFFER_HEIGHT:
+            ctx->fb_height = value;
+            break;
+        case COPYBIT_ROTATION_DEG:
+        case COPYBIT_DITHER:
+        case COPYBIT_BLUR:
+        case COPYBIT_BLIT_TO_FRAMEBUFFER:
+            // Do nothing
+            break;
+        case COPYBIT_SRC_FORMAT_MODE:
+            ctx->is_src_ubwc_format = (value == COPYBIT_UBWC_COMPRESSED);
+            break;
+        case COPYBIT_DST_FORMAT_MODE:
+            ctx->is_dst_ubwc_format = (value == COPYBIT_UBWC_COMPRESSED);
+            break;
+        default:
+            ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
+            status = -EINVAL;
+            break;
+    }
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    return status;
+}
+
+/** Get a static info value */
+static int get(struct copybit_device_t *dev, int name)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int value;
+
+    if (!ctx) {
+        ALOGE("%s: null context error", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    switch(name) {
+        case COPYBIT_MINIFICATION_LIMIT:
+            value = MAX_SCALE_FACTOR;
+            break;
+        case COPYBIT_MAGNIFICATION_LIMIT:
+            value = MAX_SCALE_FACTOR;
+            break;
+        case COPYBIT_SCALING_FRAC_BITS:
+            value = 32;
+            break;
+        case COPYBIT_ROTATION_STEP_DEG:
+            value = 1;
+            break;
+        case COPYBIT_UBWC_SUPPORT:
+            value = 0;
+            if (ctx->c2d_driver_info.capabilities_mask & C2D_DRIVER_SUPPORTS_UBWC_COMPRESSED_OP) {
+                value = 1;
+            }
+            break;
+        default:
+            ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
+            value = -EINVAL;
+    }
+    return value;
+}
+
+/* Function to check if we need a temporary buffer for the blit.
+ * This would happen if the requested destination stride and the
+ * C2D stride do not match. We ignore RGB buffers, since their
+ * stride is always aligned to 32.
+ */
+static bool need_temp_buffer(struct copybit_image_t const *img)
+{
+    if (COPYBIT_SUCCESS == is_supported_rgb_format(img->format))
+        return false;
+
+    struct private_handle_t* handle = (struct private_handle_t*)img->handle;
+
+    // The width parameter in the handle contains the aligned_w. We check if we
+    // need to convert based on this param. YUV formats have bpp=1, so checking
+    // if the requested stride is aligned should suffice.
+    if (0 == (handle->width)%32) {
+        return false;
+    }
+
+    return true;
+}
+
+/* Function to extract the information from the copybit image and set the corresponding
+ * values in the bufferInfo struct.
+ */
+static void populate_buffer_info(struct copybit_image_t const *img, bufferInfo& info)
+{
+    info.width = img->w;
+    info.height = img->h;
+    info.format = img->format;
+}
+
+/* Function to get the required size for a particular format, inorder for C2D to perform
+ * the blit operation.
+ */
+static int get_size(const bufferInfo& info)
+{
+    int size = 0;
+    int w = info.width;
+    int h = info.height;
+    int aligned_w = ALIGN(w, 32);
+    switch(info.format) {
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+            {
+                // Chroma for this format is aligned to 2K.
+                size = ALIGN((aligned_w*h), 2048) +
+                        ALIGN(aligned_w/2, 32) * (h/2) *2;
+                size = ALIGN(size, 4096);
+            } break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            {
+                size = aligned_w * h +
+                       ALIGN(aligned_w/2, 32) * (h/2) * 2;
+                size = ALIGN(size, 4096);
+            } break;
+        default: break;
+    }
+    return size;
+}
+
+/* Function to allocate memory for the temporary buffer. This memory is
+ * allocated from Ashmem. It is the caller's responsibility to free this
+ * memory.
+ */
+static int get_temp_buffer(const bufferInfo& info, alloc_data& data)
+{
+    ALOGD("%s E", __FUNCTION__);
+    // Alloc memory from system heap
+    data.base = 0;
+    data.fd = -1;
+    data.offset = 0;
+    data.size = get_size(info);
+    data.align = getpagesize();
+    data.uncached = true;
+    int allocFlags = 0;
+
+    if (sAlloc == 0) {
+        sAlloc = gralloc::IAllocController::getInstance();
+    }
+
+    if (sAlloc == 0) {
+        ALOGE("%s: sAlloc is still NULL", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    int err = sAlloc->allocate(data, allocFlags);
+    if (0 != err) {
+        ALOGE("%s: allocate failed", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    ALOGD("%s X", __FUNCTION__);
+    return err;
+}
+
+/* Function to free the temporary allocated memory.*/
+static void free_temp_buffer(alloc_data &data)
+{
+    if (-1 != data.fd) {
+        IMemAlloc* memalloc = sAlloc->getAllocator(data.allocType);
+        memalloc->free_buffer(data.base, data.size, 0, data.fd);
+    }
+}
+
+/* Function to perform the software color conversion. Convert the
+ * C2D compatible format to the Android compatible format
+ */
+static int copy_image(private_handle_t *src_handle,
+                      struct copybit_image_t const *rhs,
+                      eConversionType conversionType)
+{
+    if (src_handle->fd == -1) {
+        ALOGE("%s: src_handle fd is invalid", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    // Copy the info.
+    int ret = COPYBIT_SUCCESS;
+    switch(rhs->format) {
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            {
+                if (CONVERT_TO_ANDROID_FORMAT == conversionType) {
+                    return convert_yuv_c2d_to_yuv_android(src_handle, rhs);
+                } else {
+                    return convert_yuv_android_to_yuv_c2d(src_handle, rhs);
+                }
+
+            } break;
+        default: {
+            ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
+            ret = COPYBIT_FAILURE;
+        } break;
+    }
+    return ret;
+}
+
+static void delete_handle(private_handle_t *handle)
+{
+    if (handle) {
+        delete handle;
+        handle = 0;
+    }
+}
+
+static bool need_to_execute_draw(eC2DFlags flags)
+{
+    if (flags & FLAGS_TEMP_SRC_DST) {
+        return true;
+    }
+    if (flags & FLAGS_YUV_DESTINATION) {
+        return true;
+    }
+    return false;
+}
+
+/** do a stretch blit type operation */
+static int stretch_copybit_internal(
+    struct copybit_device_t *dev,
+    struct copybit_image_t const *dst,
+    struct copybit_image_t const *src,
+    struct copybit_rect_t const *dst_rect,
+    struct copybit_rect_t const *src_rect,
+    struct copybit_region_t const *region,
+    bool enableBlend)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int status = COPYBIT_SUCCESS;
+    int flags = 0;
+    int src_surface_type;
+    int mapped_src_idx = -1, mapped_dst_idx = -1;
+    C2D_OBJECT_STR src_surface;
+
+    if (!ctx) {
+        ALOGE("%s: null context error", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
+        ALOGE("%s: src dimension error", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
+        ALOGE("%s : dst dimension error dst w %d h %d",  __FUNCTION__, dst->w,
+                                                         dst->h);
+        return -EINVAL;
+    }
+
+    if (is_valid_destination_format(dst->format) == COPYBIT_FAILURE) {
+        ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__,
+                                                              dst->format);
+        return COPYBIT_FAILURE;
+    }
+
+    int dst_surface_type;
+    if (ctx->is_dst_ubwc_format)
+        flags |= FLAGS_UBWC_FORMAT_MODE;
+
+    if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) {
+        dst_surface_type = RGB_SURFACE;
+        flags |= FLAGS_PREMULTIPLIED_ALPHA;
+    } else if (is_supported_yuv_format(dst->format) == COPYBIT_SUCCESS) {
+        int num_planes = get_num_planes(dst->format);
+        flags |= FLAGS_YUV_DESTINATION;
+        if (num_planes == 2) {
+            dst_surface_type = YUV_SURFACE_2_PLANES;
+        } else if (num_planes == 3) {
+            dst_surface_type = YUV_SURFACE_3_PLANES;
+        } else {
+            ALOGE("%s: dst number of YUV planes is invalid dst format = 0x%x",
+                  __FUNCTION__, dst->format);
+            return COPYBIT_FAILURE;
+        }
+    } else {
+        ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__,
+                                                     dst->format);
+        return COPYBIT_FAILURE;
+    }
+
+    if (ctx->blit_rgb_count == MAX_RGB_SURFACES ||
+        ctx->blit_yuv_2_plane_count == MAX_YUV_2_PLANE_SURFACES ||
+        ctx->blit_yuv_3_plane_count == MAX_YUV_2_PLANE_SURFACES ||
+        ctx->blit_count == MAX_BLIT_OBJECT_COUNT ||
+        ctx->dst_surface_type != dst_surface_type) {
+        // we have reached the max. limits of our internal structures or
+        // changed the target.
+        // Draw the remaining surfaces. We need to do the finish here since
+        // we need to free up the surface templates.
+        finish_copybit(dev);
+    }
+
+    ctx->dst_surface_type = dst_surface_type;
+
+    // Update the destination
+    copybit_image_t dst_image;
+    dst_image.w = dst->w;
+    dst_image.h = dst->h;
+    dst_image.format = dst->format;
+    dst_image.handle = dst->handle;
+    // Check if we need a temp. copy for the destination. We'd need this the destination
+    // width is not aligned to 32. This case occurs for YUV formats. RGB formats are
+    // aligned to 32.
+    bool need_temp_dst = need_temp_buffer(dst);
+    bufferInfo dst_info;
+    populate_buffer_info(dst, dst_info);
+    private_handle_t* dst_hnd = new private_handle_t(-1, 0, 0, 0, dst_info.format,
+                                                     dst_info.width, dst_info.height);
+    if (dst_hnd == NULL) {
+        ALOGE("%s: dst_hnd is null", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+    if (need_temp_dst) {
+        if (get_size(dst_info) != (int) ctx->temp_dst_buffer.size) {
+            free_temp_buffer(ctx->temp_dst_buffer);
+            // Create a temp buffer and set that as the destination.
+            if (COPYBIT_FAILURE == get_temp_buffer(dst_info, ctx->temp_dst_buffer)) {
+                ALOGE("%s: get_temp_buffer(dst) failed", __FUNCTION__);
+                delete_handle(dst_hnd);
+                return COPYBIT_FAILURE;
+            }
+        }
+        dst_hnd->fd = ctx->temp_dst_buffer.fd;
+        dst_hnd->size = ctx->temp_dst_buffer.size;
+        dst_hnd->flags = ctx->temp_dst_buffer.allocType;
+        dst_hnd->base = (uintptr_t)(ctx->temp_dst_buffer.base);
+        dst_hnd->offset = ctx->temp_dst_buffer.offset;
+        dst_hnd->gpuaddr = 0;
+        dst_image.handle = dst_hnd;
+    }
+    if(!ctx->dst_surface_mapped) {
+        //map the destination surface to GPU address
+        status = set_image(ctx, ctx->dst[ctx->dst_surface_type], &dst_image,
+                           (eC2DFlags)flags, mapped_dst_idx);
+        if(status) {
+            ALOGE("%s: dst: set_image error", __FUNCTION__);
+            delete_handle(dst_hnd);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
+            return COPYBIT_FAILURE;
+        }
+        ctx->dst_surface_mapped = true;
+        ctx->dst_surface_base = dst->base;
+    } else if(ctx->dst_surface_mapped && ctx->dst_surface_base != dst->base) {
+        // Destination surface for the operation should be same for multiple
+        // requests, this check is catch if there is any case when the
+        // destination changes
+        ALOGE("%s: a different destination surface!!", __FUNCTION__);
+    }
+
+    // Update the source
+    flags = 0;
+    if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) {
+        src_surface_type = RGB_SURFACE;
+        src_surface = ctx->blit_rgb_object[ctx->blit_rgb_count];
+    } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) {
+        int num_planes = get_num_planes(src->format);
+        if (num_planes == 2) {
+            src_surface_type = YUV_SURFACE_2_PLANES;
+            src_surface = ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count];
+        } else if (num_planes == 3) {
+            src_surface_type = YUV_SURFACE_3_PLANES;
+            src_surface = ctx->blit_yuv_3_plane_object[ctx->blit_yuv_2_plane_count];
+        } else {
+            ALOGE("%s: src number of YUV planes is invalid src format = 0x%x",
+                  __FUNCTION__, src->format);
+            delete_handle(dst_hnd);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
+            return -EINVAL;
+        }
+    } else {
+        ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__,
+                                                        src->format);
+        delete_handle(dst_hnd);
+        unmap_gpuaddr(ctx, mapped_dst_idx);
+        return -EINVAL;
+    }
+
+    copybit_image_t src_image;
+    src_image.w = src->w;
+    src_image.h = src->h;
+    src_image.format = src->format;
+    src_image.handle = src->handle;
+
+    bool need_temp_src = need_temp_buffer(src);
+    bufferInfo src_info;
+    populate_buffer_info(src, src_info);
+    private_handle_t* src_hnd = new private_handle_t(-1, 0, 0, 0, src_info.format,
+                                                 src_info.width, src_info.height);
+    if (NULL == src_hnd) {
+        ALOGE("%s: src_hnd is null", __FUNCTION__);
+        delete_handle(dst_hnd);
+        unmap_gpuaddr(ctx, mapped_dst_idx);
+        return COPYBIT_FAILURE;
+    }
+    if (need_temp_src) {
+        if (get_size(src_info) != (int) ctx->temp_src_buffer.size) {
+            free_temp_buffer(ctx->temp_src_buffer);
+            // Create a temp buffer and set that as the destination.
+            if (COPYBIT_SUCCESS != get_temp_buffer(src_info,
+                                               ctx->temp_src_buffer)) {
+                ALOGE("%s: get_temp_buffer(src) failed", __FUNCTION__);
+                delete_handle(dst_hnd);
+                delete_handle(src_hnd);
+                unmap_gpuaddr(ctx, mapped_dst_idx);
+                return COPYBIT_FAILURE;
+            }
+        }
+        src_hnd->fd = ctx->temp_src_buffer.fd;
+        src_hnd->size = ctx->temp_src_buffer.size;
+        src_hnd->flags = ctx->temp_src_buffer.allocType;
+        src_hnd->base = (uintptr_t)(ctx->temp_src_buffer.base);
+        src_hnd->offset = ctx->temp_src_buffer.offset;
+        src_hnd->gpuaddr = 0;
+        src_image.handle = src_hnd;
+
+        // Copy the source.
+        status = copy_image((private_handle_t *)src->handle, &src_image,
+                                CONVERT_TO_C2D_FORMAT);
+        if (status == COPYBIT_FAILURE) {
+            ALOGE("%s:copy_image failed in temp source",__FUNCTION__);
+            delete_handle(dst_hnd);
+            delete_handle(src_hnd);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
+            return status;
+        }
+
+        // Clean the cache
+        IMemAlloc* memalloc = sAlloc->getAllocator(src_hnd->flags);
+        if (memalloc->clean_buffer((void *)(src_hnd->base), src_hnd->size,
+                                   src_hnd->offset, src_hnd->fd,
+                                   gralloc::CACHE_CLEAN)) {
+            ALOGE("%s: clean_buffer failed", __FUNCTION__);
+            delete_handle(dst_hnd);
+            delete_handle(src_hnd);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
+            return COPYBIT_FAILURE;
+        }
+    }
+
+    flags |= (ctx->is_premultiplied_alpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0;
+    flags |= (ctx->dst_surface_type != RGB_SURFACE) ? FLAGS_YUV_DESTINATION : 0;
+    flags |= (ctx->is_src_ubwc_format) ? FLAGS_UBWC_FORMAT_MODE : 0;
+    status = set_image(ctx, src_surface.surface_id, &src_image,
+                       (eC2DFlags)flags, mapped_src_idx);
+    if(status) {
+        ALOGE("%s: set_image (src) error", __FUNCTION__);
+        delete_handle(dst_hnd);
+        delete_handle(src_hnd);
+        unmap_gpuaddr(ctx, mapped_dst_idx);
+        unmap_gpuaddr(ctx, mapped_src_idx);
+        return COPYBIT_FAILURE;
+    }
+
+    src_surface.config_mask = C2D_NO_ANTIALIASING_BIT | ctx->config_mask;
+    src_surface.global_alpha = ctx->src_global_alpha;
+    if (enableBlend) {
+        if(src_surface.config_mask & C2D_GLOBAL_ALPHA_BIT) {
+            src_surface.config_mask &= ~C2D_ALPHA_BLEND_NONE;
+            if(!(src_surface.global_alpha)) {
+                // src alpha is zero
+                delete_handle(dst_hnd);
+                delete_handle(src_hnd);
+                unmap_gpuaddr(ctx, mapped_dst_idx);
+                unmap_gpuaddr(ctx, mapped_src_idx);
+                return COPYBIT_FAILURE;
+            }
+        }
+    } else {
+        src_surface.config_mask |= C2D_ALPHA_BLEND_NONE;
+    }
+
+    if (src_surface_type == RGB_SURFACE) {
+        ctx->blit_rgb_object[ctx->blit_rgb_count] = src_surface;
+        ctx->blit_rgb_count++;
+    } else if (src_surface_type == YUV_SURFACE_2_PLANES) {
+        ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count] = src_surface;
+        ctx->blit_yuv_2_plane_count++;
+    } else {
+        ctx->blit_yuv_3_plane_object[ctx->blit_yuv_3_plane_count] = src_surface;
+        ctx->blit_yuv_3_plane_count++;
+    }
+
+    struct copybit_rect_t clip;
+    while ((status == 0) && region->next(region, &clip)) {
+        set_rects(ctx, &(src_surface), dst_rect, src_rect, &clip);
+        if (ctx->blit_count == MAX_BLIT_OBJECT_COUNT) {
+            ALOGW("Reached end of blit count");
+            finish_copybit(dev);
+        }
+        ctx->blit_list[ctx->blit_count] = src_surface;
+        ctx->blit_count++;
+    }
+
+    // Check if we need to perform an early draw-finish.
+    flags |= (need_temp_dst || need_temp_src) ? FLAGS_TEMP_SRC_DST : 0;
+    if (need_to_execute_draw((eC2DFlags)flags))
+    {
+        finish_copybit(dev);
+    }
+
+    if (need_temp_dst) {
+        // copy the temp. destination without the alignment to the actual
+        // destination.
+        status = copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT);
+        if (status == COPYBIT_FAILURE) {
+            ALOGE("%s:copy_image failed in temp Dest",__FUNCTION__);
+            delete_handle(dst_hnd);
+            delete_handle(src_hnd);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
+            unmap_gpuaddr(ctx, mapped_src_idx);
+            return status;
+        }
+        // Clean the cache.
+        IMemAlloc* memalloc = sAlloc->getAllocator(dst_hnd->flags);
+        memalloc->clean_buffer((void *)(dst_hnd->base), dst_hnd->size,
+                               dst_hnd->offset, dst_hnd->fd,
+                               gralloc::CACHE_CLEAN);
+    }
+    delete_handle(dst_hnd);
+    delete_handle(src_hnd);
+
+    ctx->is_premultiplied_alpha = false;
+    ctx->fb_width = 0;
+    ctx->fb_height = 0;
+    ctx->config_mask = 0;
+    return status;
+}
+
+static int set_sync_copybit(struct copybit_device_t *dev,
+    int /*acquireFenceFd*/)
+{
+    if(!dev)
+        return -EINVAL;
+
+    return 0;
+}
+
+static int stretch_copybit(
+    struct copybit_device_t *dev,
+    struct copybit_image_t const *dst,
+    struct copybit_image_t const *src,
+    struct copybit_rect_t const *dst_rect,
+    struct copybit_rect_t const *src_rect,
+    struct copybit_region_t const *region)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int status = COPYBIT_SUCCESS;
+    bool needsBlending = (ctx->src_global_alpha != 0);
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    status = stretch_copybit_internal(dev, dst, src, dst_rect, src_rect,
+                                    region, needsBlending);
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    return status;
+}
+
+/** Perform a blit type operation */
+static int blit_copybit(
+    struct copybit_device_t *dev,
+    struct copybit_image_t const *dst,
+    struct copybit_image_t const *src,
+    struct copybit_region_t const *region)
+{
+    int status = COPYBIT_SUCCESS;
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    struct copybit_rect_t dr = { 0, 0, (int)dst->w, (int)dst->h };
+    struct copybit_rect_t sr = { 0, 0, (int)src->w, (int)src->h };
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    status = stretch_copybit_internal(dev, dst, src, &dr, &sr, region, false);
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    return status;
+}
+
+/** Fill the rect on dst with RGBA color **/
+static int fill_color(struct copybit_device_t *dev,
+                      struct copybit_image_t const *dst,
+                      struct copybit_rect_t const *rect,
+                      uint32_t /*color*/)
+{
+    // TODO: Implement once c2d driver supports color fill
+    if(!dev || !dst || !rect)
+       return -EINVAL;
+
+    return -EINVAL;
+}
+
+/*****************************************************************************/
+
+static void clean_up(copybit_context_t* ctx)
+{
+    void* ret;
+    if (!ctx)
+        return;
+
+    // stop the wait_cleanup_thread
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    ctx->stop_thread = true;
+    // Signal waiting thread
+    pthread_cond_signal(&ctx->wait_cleanup_cond);
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    // waits for the cleanup thread to exit
+    pthread_join(ctx->wait_thread_id, &ret);
+    pthread_mutex_destroy(&ctx->wait_cleanup_lock);
+    pthread_cond_destroy (&ctx->wait_cleanup_cond);
+
+    for (int i = 0; i < NUM_SURFACE_TYPES; i++) {
+        if (ctx->dst[i])
+            LINK_c2dDestroySurface(ctx->dst[i]);
+    }
+
+    for (int i = 0; i < MAX_RGB_SURFACES; i++) {
+        if (ctx->blit_rgb_object[i].surface_id)
+            LINK_c2dDestroySurface(ctx->blit_rgb_object[i].surface_id);
+    }
+
+    for (int i = 0; i < MAX_YUV_2_PLANE_SURFACES; i++) {
+        if (ctx->blit_yuv_2_plane_object[i].surface_id)
+            LINK_c2dDestroySurface(ctx->blit_yuv_2_plane_object[i].surface_id);
+    }
+
+    for (int i = 0; i < MAX_YUV_3_PLANE_SURFACES; i++) {
+        if (ctx->blit_yuv_3_plane_object[i].surface_id)
+            LINK_c2dDestroySurface(ctx->blit_yuv_3_plane_object[i].surface_id);
+    }
+
+    if (ctx->libc2d2) {
+        ::dlclose(ctx->libc2d2);
+        ALOGV("dlclose(libc2d2)");
+    }
+
+    free(ctx);
+}
+
+/** Close the copybit device */
+static int close_copybit(struct hw_device_t *dev)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (ctx) {
+        free_temp_buffer(ctx->temp_src_buffer);
+        free_temp_buffer(ctx->temp_dst_buffer);
+    }
+    clean_up(ctx);
+    return 0;
+}
+
+/** Open a new instance of a copybit device using name */
+static int open_copybit(const struct hw_module_t* module, const char* name,
+                        struct hw_device_t** device)
+{
+    int status = COPYBIT_SUCCESS;
+    if (strcmp(name, COPYBIT_HARDWARE_COPYBIT0)) {
+        return COPYBIT_FAILURE;
+    }
+
+    C2D_RGB_SURFACE_DEF surfDefinition = {0};
+    C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ;
+    struct copybit_context_t *ctx;
+
+    ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t));
+    if(!ctx) {
+        ALOGE("%s: malloc failed", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    /* initialize drawstate */
+    memset(ctx, 0, sizeof(*ctx));
+    ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW);
+    if (!ctx->libc2d2) {
+        ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+    *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2,
+                                               "c2dCreateSurface");
+    *(void **)&LINK_c2dUpdateSurface = ::dlsym(ctx->libc2d2,
+                                               "c2dUpdateSurface");
+    *(void **)&LINK_c2dReadSurface = ::dlsym(ctx->libc2d2,
+                                             "c2dReadSurface");
+    *(void **)&LINK_c2dDraw = ::dlsym(ctx->libc2d2, "c2dDraw");
+    *(void **)&LINK_c2dFlush = ::dlsym(ctx->libc2d2, "c2dFlush");
+    *(void **)&LINK_c2dFinish = ::dlsym(ctx->libc2d2, "c2dFinish");
+    *(void **)&LINK_c2dWaitTimestamp = ::dlsym(ctx->libc2d2,
+                                               "c2dWaitTimestamp");
+    *(void **)&LINK_c2dDestroySurface = ::dlsym(ctx->libc2d2,
+                                                "c2dDestroySurface");
+    *(void **)&LINK_c2dMapAddr = ::dlsym(ctx->libc2d2,
+                                         "c2dMapAddr");
+    *(void **)&LINK_c2dUnMapAddr = ::dlsym(ctx->libc2d2,
+                                           "c2dUnMapAddr");
+    *(void **)&LINK_c2dGetDriverCapabilities = ::dlsym(ctx->libc2d2,
+                                           "c2dGetDriverCapabilities");
+    *(void **)&LINK_c2dCreateFenceFD = ::dlsym(ctx->libc2d2,
+                                           "c2dCreateFenceFD");
+    *(void **)&LINK_c2dFillSurface = ::dlsym(ctx->libc2d2,
+                                           "c2dFillSurface");
+
+    if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface
+        || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp ||
+        !LINK_c2dFinish  || !LINK_c2dDestroySurface ||
+        !LINK_c2dGetDriverCapabilities || !LINK_c2dCreateFenceFD ||
+        !LINK_c2dFillSurface) {
+        ALOGE("%s: dlsym ERROR", __FUNCTION__);
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    ctx->device.common.tag = HARDWARE_DEVICE_TAG;
+    ctx->device.common.version = 1;
+    ctx->device.common.module = (hw_module_t*)(module);
+    ctx->device.common.close = close_copybit;
+    ctx->device.set_parameter = set_parameter_copybit;
+    ctx->device.get = get;
+    ctx->device.blit = blit_copybit;
+    ctx->device.set_sync = set_sync_copybit;
+    ctx->device.stretch = stretch_copybit;
+    ctx->device.finish = finish_copybit;
+    ctx->device.flush_get_fence = flush_get_fence_copybit;
+    ctx->device.clear = clear_copybit;
+    ctx->device.fill_color = fill_color;
+
+    /* Create RGB Surface */
+    surfDefinition.buffer = (void*)0xdddddddd;
+    surfDefinition.phys = (void*)0xdddddddd;
+    surfDefinition.stride = 1 * 4;
+    surfDefinition.width = 1;
+    surfDefinition.height = 1;
+    surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB;
+    if (LINK_c2dCreateSurface(&(ctx->dst[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY ),
+                                                 &surfDefinition)) {
+        ALOGE("%s: create ctx->dst_surface[RGB_SURFACE] failed", __FUNCTION__);
+        ctx->dst[RGB_SURFACE] = 0;
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    unsigned int surface_id = 0;
+    for (int i = 0; i < MAX_RGB_SURFACES; i++)
+    {
+        if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY ),
+                                                 &surfDefinition)) {
+            ALOGE("%s: create RGB source surface %d failed", __FUNCTION__, i);
+            ctx->blit_rgb_object[i].surface_id = 0;
+            status = COPYBIT_FAILURE;
+            break;
+        } else {
+            ctx->blit_rgb_object[i].surface_id = surface_id;
+            ALOGW("%s i = %d surface_id=%d",  __FUNCTION__, i,
+                                          ctx->blit_rgb_object[i].surface_id);
+        }
+    }
+
+    if (status == COPYBIT_FAILURE) {
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    // Create 2 plane YUV surfaces
+    yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12;
+    yuvSurfaceDef.width = 4;
+    yuvSurfaceDef.height = 4;
+    yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa;
+    yuvSurfaceDef.phys0 = (void*) 0xaaaaaaaa;
+    yuvSurfaceDef.stride0 = 4;
+
+    yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa;
+    yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa;
+    yuvSurfaceDef.stride1 = 4;
+    if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_2_PLANES]),
+                              C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
+                               C2D_SURFACE_WITH_PHYS |
+                               C2D_SURFACE_WITH_PHYS_DUMMY),
+                              &yuvSurfaceDef)) {
+        ALOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
+        ctx->dst[YUV_SURFACE_2_PLANES] = 0;
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    for (int i=0; i < MAX_YUV_2_PLANE_SURFACES; i++)
+    {
+        if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY ),
+                              &yuvSurfaceDef)) {
+            ALOGE("%s: create YUV source %d failed", __FUNCTION__, i);
+            ctx->blit_yuv_2_plane_object[i].surface_id = 0;
+            status = COPYBIT_FAILURE;
+            break;
+        } else {
+            ctx->blit_yuv_2_plane_object[i].surface_id = surface_id;
+            ALOGW("%s: 2 Plane YUV i=%d surface_id=%d",  __FUNCTION__, i,
+                                   ctx->blit_yuv_2_plane_object[i].surface_id);
+        }
+    }
+
+    if (status == COPYBIT_FAILURE) {
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    // Create YUV 3 plane surfaces
+    yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_YV12;
+    yuvSurfaceDef.plane2 = (void*)0xaaaaaaaa;
+    yuvSurfaceDef.phys2 = (void*) 0xaaaaaaaa;
+    yuvSurfaceDef.stride2 = 4;
+
+    if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]),
+                              C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY),
+                              &yuvSurfaceDef)) {
+        ALOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
+        ctx->dst[YUV_SURFACE_3_PLANES] = 0;
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    for (int i=0; i < MAX_YUV_3_PLANE_SURFACES; i++)
+    {
+        if (LINK_c2dCreateSurface(&(surface_id),
+                              C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY),
+                              &yuvSurfaceDef)) {
+            ALOGE("%s: create 3 plane YUV surface %d failed", __FUNCTION__, i);
+            ctx->blit_yuv_3_plane_object[i].surface_id = 0;
+            status = COPYBIT_FAILURE;
+            break;
+        } else {
+            ctx->blit_yuv_3_plane_object[i].surface_id = surface_id;
+            ALOGW("%s: 3 Plane YUV i=%d surface_id=%d",  __FUNCTION__, i,
+                                   ctx->blit_yuv_3_plane_object[i].surface_id);
+        }
+    }
+
+    if (status == COPYBIT_FAILURE) {
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    if (LINK_c2dGetDriverCapabilities(&(ctx->c2d_driver_info))) {
+         ALOGE("%s: LINK_c2dGetDriverCapabilities failed", __FUNCTION__);
+         clean_up(ctx);
+         status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+    // Initialize context variables.
+    ctx->trg_transform = C2D_TARGET_ROTATE_0;
+
+    ctx->temp_src_buffer.fd = -1;
+    ctx->temp_src_buffer.base = 0;
+    ctx->temp_src_buffer.size = 0;
+
+    ctx->temp_dst_buffer.fd = -1;
+    ctx->temp_dst_buffer.base = 0;
+    ctx->temp_dst_buffer.size = 0;
+
+    ctx->fb_width = 0;
+    ctx->fb_height = 0;
+
+    ctx->blit_rgb_count = 0;
+    ctx->blit_yuv_2_plane_count = 0;
+    ctx->blit_yuv_3_plane_count = 0;
+    ctx->blit_count = 0;
+
+    ctx->wait_timestamp = false;
+    ctx->stop_thread = false;
+    pthread_mutex_init(&(ctx->wait_cleanup_lock), NULL);
+    pthread_cond_init(&(ctx->wait_cleanup_cond), NULL);
+    /* Start the wait thread */
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+    pthread_create(&ctx->wait_thread_id, &attr, &c2d_wait_loop,
+                                                            (void *)ctx);
+    pthread_attr_destroy(&attr);
+
+    *device = &ctx->device.common;
+    return status;
+}
diff --git a/sdm845/libcopybit/copybit_priv.h b/sdm845/libcopybit/copybit_priv.h
new file mode 100644
index 0000000..68dfac4
--- /dev/null
+++ b/sdm845/libcopybit/copybit_priv.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011, 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 <copybit.h>
+struct copybit_iterator : public copybit_region_t {
+    copybit_iterator(const copybit_rect_t& rect) {
+        mRect = rect;
+        mCount = 1;
+        this->next = iterate;
+    }
+private:
+    static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
+        if (!self || !rect) {
+            return 0;
+        }
+
+        copybit_iterator const* me = static_cast<copybit_iterator const*>(self);
+        if (me->mCount) {
+            rect->l = me->mRect.l;
+            rect->t = me->mRect.t;
+            rect->r = me->mRect.r;
+            rect->b = me->mRect.b;
+            me->mCount--;
+            return 1;
+        }
+        return 0;
+    }
+    copybit_rect_t mRect;
+    mutable int mCount;
+};
diff --git a/sdm845/libcopybit/software_converter.cpp b/sdm845/libcopybit/software_converter.cpp
new file mode 100644
index 0000000..e5c03b5
--- /dev/null
+++ b/sdm845/libcopybit/software_converter.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2011-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 <cutils/log.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "software_converter.h"
+
+/** Convert YV12 to YCrCb_420_SP */
+int convertYV12toYCrCb420SP(const copybit_image_t *src, private_handle_t *yv12_handle)
+{
+    private_handle_t* hnd = (private_handle_t*)src->handle;
+
+    if(hnd == NULL || yv12_handle == NULL){
+        ALOGE("Invalid handle");
+        return -1;
+    }
+
+    // Please refer to the description of YV12 in hardware.h
+    // for the formulae used to calculate buffer sizes and offsets
+
+    // In a copybit_image_t, w is the stride and
+    // stride - horiz_padding is the actual width
+    // vertical stride is the same as height, so not considered
+    unsigned int   stride  = src->w;
+    unsigned int   width   = src->w - src->horiz_padding;
+    unsigned int   height  = src->h;
+    unsigned int   y_size  = stride * src->h;
+    unsigned int   c_width = ALIGN(stride/2, (unsigned int)16);
+    unsigned int   c_size  = c_width * src->h/2;
+    unsigned int   chromaPadding = c_width - width/2;
+    unsigned int   chromaSize = c_size * 2;
+    unsigned char* newChroma = (unsigned char *)(yv12_handle->base + y_size);
+    unsigned char* oldChroma = (unsigned char*)(hnd->base + y_size);
+    memcpy((char *)yv12_handle->base,(char *)hnd->base,y_size);
+
+#if defined(__ARM_HAVE_NEON) && !defined(__aarch64__)
+   /* interleave */
+    if(!chromaPadding) {
+        unsigned char * t1 = newChroma;
+        unsigned char * t2 = oldChroma;
+        unsigned char * t3 = t2 + chromaSize/2;
+        for(unsigned int i=0; i < (chromaSize/2)>>3; i++) {
+            __asm__ __volatile__ (
+                                    "vld1.u8 d0, [%0]! \n"
+                                    "vld1.u8 d1, [%1]! \n"
+                                    "vst2.u8 {d0, d1}, [%2]! \n"
+                                    :"+r"(t2), "+r"(t3), "+r"(t1)
+                                    :
+                                    :"memory","d0","d1"
+                                 );
+
+        }
+    }
+#else  //__ARM_HAVE_NEON
+    if(!chromaPadding) {
+        for(unsigned int i = 0; i< chromaSize/2; i++) {
+            newChroma[i*2]   = oldChroma[i];
+            newChroma[i*2+1] = oldChroma[i+chromaSize/2];
+        }
+
+    }
+#endif
+    // If the image is not aligned to 16 pixels,
+    // convert using the C routine below
+    // r1 tracks the row of the source buffer
+    // r2 tracks the row of the destination buffer
+    // The width/2 checks are to avoid copying
+    // from the padding
+
+    if(chromaPadding) {
+        unsigned int r1 = 0, r2 = 0, i = 0, j = 0;
+        while(r1 < height/2) {
+            if(j == width) {
+                j = 0;
+                r2++;
+                continue;
+            }
+            if (j+1 == width) {
+                newChroma[r2*width + j] = oldChroma[r1*c_width+i];
+                r2++;
+                newChroma[r2*width] = oldChroma[r1*c_width+i+c_size];
+                j = 1;
+            } else {
+                newChroma[r2*width + j] = oldChroma[r1*c_width+i];
+                newChroma[r2*width + j + 1] = oldChroma[r1*c_width+i+c_size];
+                j+=2;
+            }
+            i++;
+            if (i == width/2 ) {
+                i = 0;
+                r1++;
+            }
+        }
+    }
+
+  return 0;
+}
+
+struct copyInfo{
+    int width;
+    int height;
+    int src_stride;
+    int dst_stride;
+    size_t src_plane1_offset;
+    size_t src_plane2_offset;
+    size_t dst_plane1_offset;
+    size_t dst_plane2_offset;
+};
+
+/* Internal function to do the actual copy of source to destination */
+static int copy_source_to_destination(const uintptr_t src_base,
+                                      const uintptr_t dst_base,
+                                      copyInfo& info)
+{
+    if (!src_base || !dst_base) {
+        ALOGE("%s: invalid memory src_base = 0x%p dst_base=0x%p",
+             __FUNCTION__, (void*)src_base, (void*)dst_base);
+         return COPYBIT_FAILURE;
+    }
+
+    int width = info.width;
+    int height = info.height;
+    unsigned char *src = (unsigned char*)src_base;
+    unsigned char *dst = (unsigned char*)dst_base;
+
+    // Copy the luma
+    for (int i = 0; i < height; i++) {
+        memcpy(dst, src, width);
+        src += info.src_stride;
+        dst += info.dst_stride;
+    }
+
+    // Copy plane 1
+    src = (unsigned char*)(src_base + info.src_plane1_offset);
+    dst = (unsigned char*)(dst_base + info.dst_plane1_offset);
+    width = width/2;
+    height = height/2;
+    for (int i = 0; i < height; i++) {
+        memcpy(dst, src, info.src_stride);
+        src += info.src_stride;
+        dst += info.dst_stride;
+    }
+    return 0;
+}
+
+
+/*
+ * Function to convert the c2d format into an equivalent Android format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_c2d_to_yuv_android(private_handle_t *hnd,
+                                   struct copybit_image_t const *rhs)
+{
+    ALOGD("Enter %s", __FUNCTION__);
+    if (!hnd || !rhs) {
+        ALOGE("%s: invalid inputs hnd=%p rhs=%p", __FUNCTION__, hnd, rhs);
+        return COPYBIT_FAILURE;
+    }
+
+    int ret = COPYBIT_SUCCESS;
+    private_handle_t *dst_hnd = (private_handle_t *)rhs->handle;
+
+    copyInfo info;
+    info.width = rhs->w;
+    info.height = rhs->h;
+    info.src_stride = ALIGN(info.width, 32);
+    info.dst_stride = ALIGN(info.width, 16);
+    switch(rhs->format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
+            info.src_plane1_offset = info.src_stride*info.height;
+            info.dst_plane1_offset = info.dst_stride*info.height;
+        } break;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: {
+            // Chroma is 2K aligned for the NV12 encodeable format.
+            info.src_plane1_offset = ALIGN(info.src_stride*info.height, 2048);
+            info.dst_plane1_offset = ALIGN(info.dst_stride*info.height, 2048);
+        } break;
+        default:
+            ALOGE("%s: unsupported format (format=0x%x)", __FUNCTION__,
+                 rhs->format);
+            return COPYBIT_FAILURE;
+    }
+
+    ret = copy_source_to_destination((uintptr_t) hnd->base, (uintptr_t) dst_hnd->base, info);
+    return ret;
+}
+
+/*
+ * Function to convert the Android format into an equivalent C2D format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_android_to_yuv_c2d(private_handle_t *hnd,
+                                   struct copybit_image_t const *rhs)
+{
+    if (!hnd || !rhs) {
+        ALOGE("%s: invalid inputs hnd=%p rhs=%p", __FUNCTION__, hnd, rhs);
+        return COPYBIT_FAILURE;
+    }
+
+    int ret = COPYBIT_SUCCESS;
+    private_handle_t *dst_hnd = (private_handle_t *)rhs->handle;
+
+    copyInfo info;
+    info.width = rhs->w;
+    info.height = rhs->h;
+    info.src_stride = ALIGN(hnd->width, 16);
+    info.dst_stride = ALIGN(info.width, 32);
+    switch(rhs->format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
+            info.src_plane1_offset = info.src_stride*info.height;
+            info.dst_plane1_offset = info.dst_stride*info.height;
+        } break;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: {
+            // Chroma is 2K aligned for the NV12 encodeable format.
+            info.src_plane1_offset = ALIGN(info.src_stride*info.height, 2048);
+            info.dst_plane1_offset = ALIGN(info.dst_stride*info.height, 2048);
+        } break;
+        default:
+            ALOGE("%s: unsupported format (format=0x%x)", __FUNCTION__,
+                 rhs->format);
+            return -1;
+    }
+
+    ret = copy_source_to_destination((uintptr_t) hnd->base, (uintptr_t) dst_hnd->base, info);
+    return ret;
+}
diff --git a/sdm845/libcopybit/software_converter.h b/sdm845/libcopybit/software_converter.h
new file mode 100644
index 0000000..cc6ae34
--- /dev/null
+++ b/sdm845/libcopybit/software_converter.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011, 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 <copybit.h>
+#include "gralloc_priv.h"
+
+#define COPYBIT_SUCCESS 0
+#define COPYBIT_FAILURE -1
+
+#define ALIGN(x, y) (((x) + y - 1) & (~(y - 1)))
+
+int convertYV12toYCrCb420SP(const copybit_image_t *src,private_handle_t *yv12_handle);
+
+/*
+ * Function to convert the c2d format into an equivalent Android format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_c2d_to_yuv_android(private_handle_t *hnd,
+                                   struct copybit_image_t const *rhs);
+
+
+/*
+ * Function to convert the Android format into an equivalent C2D format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_android_to_yuv_c2d(private_handle_t *hnd,
+                                   struct copybit_image_t const *rhs);
diff --git a/sdm845/libdrmutils/Android.mk b/sdm845/libdrmutils/Android.mk
new file mode 100644
index 0000000..ebcfc8a
--- /dev/null
+++ b/sdm845/libdrmutils/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := libdrmutils
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := external/libdrm \
+                                 $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_SHARED_LIBRARIES        := libdrm libdl
+LOCAL_CFLAGS                  := -DLOG_TAG=\"DRMUTILS\" -Wall -std=c++11 -Werror -fno-operator-names
+LOCAL_CLANG                   := true
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+LOCAL_SRC_FILES               := drm_master.cpp drm_res_mgr.cpp drm_lib_loader.cpp
+LOCAL_COPY_HEADERS_TO         := qcom/display
+LOCAL_COPY_HEADERS            := drm_master.h drm_res_mgr.h drm_lib_loader.h drm_logger.h drm_interface.h
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/sdm845/libdrmutils/drm_interface.h b/sdm845/libdrmutils/drm_interface.h
new file mode 100644
index 0000000..71767e7
--- /dev/null
+++ b/sdm845/libdrmutils/drm_interface.h
@@ -0,0 +1,524 @@
+/*
+* Copyright (c) 2017, 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 __DRM_INTERFACE_H__
+#define __DRM_INTERFACE_H__
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+
+namespace sde_drm {
+
+typedef std::map<std::pair<uint32_t, uint64_t>, float> CompRatioMap;
+
+/*
+ * Drm Atomic Operation Codes
+ */
+enum struct DRMOps {
+  /*
+   * Op: Sets plane source crop
+   * Arg: uint32_t - Plane ID
+   *      DRMRect  - Source Rectangle
+   */
+  PLANE_SET_SRC_RECT,
+  /*
+   * Op: Sets plane destination rect
+   * Arg: uint32_t - Plane ID
+   *      DRMRect - Dst Rectangle
+   */
+  PLANE_SET_DST_RECT,
+  /*
+   * Op: Sets plane zorder
+   * Arg: uint32_t - Plane ID
+   *      uint32_t - zorder
+   */
+  PLANE_SET_ZORDER,
+  /*
+   * Op: Sets plane rotation flags
+   * Arg: uint32_t - Plane ID
+   *      uint32_t - bit mask of rotation flags (See drm_mode.h for enums)
+   */
+  PLANE_SET_ROTATION,
+  /*
+   * Op: Sets plane alpha
+   * Arg: uint32_t - Plane ID
+   *      uint32_t - alpha value
+   */
+  PLANE_SET_ALPHA,
+  /*
+   * Op: Sets the blend type
+   * Arg: uint32_t - Plane ID
+   *      uint32_t - blend type (see DRMBlendType)
+   */
+  PLANE_SET_BLEND_TYPE,
+  /*
+   * Op: Sets horizontal decimation
+   * Arg: uint32_t - Plane ID
+   *      uint32_t - decimation factor
+   */
+  PLANE_SET_H_DECIMATION,
+  /*
+   * Op: Sets vertical decimation
+   * Arg: uint32_t - Plane ID
+   *      uint32_t - decimation factor
+   */
+  PLANE_SET_V_DECIMATION,
+  /*
+   * Op: Sets source config flags
+   * Arg: uint32_t - Plane ID
+   *      uint32_t - flags to enable or disable a specific op. E.g. deinterlacing
+   */
+  PLANE_SET_SRC_CONFIG,
+  /*
+   * Op: Sets frame buffer ID for plane. Set together with CRTC.
+   * Arg: uint32_t - Plane ID
+   *      uint32_t - Framebuffer ID
+   */
+  PLANE_SET_FB_ID,
+  /*
+   * Op: Sets the crtc for this plane. Set together with FB_ID.
+   * Arg: uint32_t - Plane ID
+   *      uint32_t - CRTC ID
+   */
+  PLANE_SET_CRTC,
+  /*
+   * Op: Sets acquire fence for this plane's buffer. Set together with FB_ID, CRTC.
+   * Arg: uint32_t - Plane ID
+   *      uint32_t - Input fence
+   */
+  PLANE_SET_INPUT_FENCE,
+  /*
+   * Op: Sets scaler config on this plane.
+   * Arg: uint32_t - Plane ID
+   *      uint64_t - Address of the scaler config object (version based)
+   */
+  PLANE_SET_SCALER_CONFIG,
+  /*
+   * Op: Activate or deactivate a CRTC
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - 1 to enable, 0 to disable
+   */
+  CRTC_SET_ACTIVE,
+  /*
+   * Op: Sets display mode
+   * Arg: uint32_t - CRTC ID
+   *      drmModeModeInfo* - Pointer to display mode
+   */
+  CRTC_SET_MODE,
+  /*
+   * Op: Sets an offset indicating when a release fence should be signalled.
+   * Arg: uint32_t - offset
+   *      0: non-speculative, default
+   *      1: speculative
+   */
+  CRTC_SET_OUTPUT_FENCE_OFFSET,
+  /*
+   * Op: Sets overall SDE core clock
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - core_clk
+   */
+  CRTC_SET_CORE_CLK,
+   /*
+   * Op: Sets overall SDE core average bandwidth
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - core_ab
+   */
+  CRTC_SET_CORE_AB,
+   /*
+   * Op: Sets overall SDE core instantaneous bandwidth
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - core_ib
+   */
+  CRTC_SET_CORE_IB,
+  /*
+   * Op: Returns release fence for this frame. Should be called after Commit() on
+   * DRMAtomicReqInterface.
+   * Arg: uint32_t - CRTC ID
+   *      int * - Pointer to an integer that will hold the returned fence
+   */
+  CRTC_GET_RELEASE_FENCE,
+  /*
+   * Op: Sets PP feature
+   * Arg: uint32_t - CRTC ID
+   *      DRMPPFeatureInfo * - PP feature data pointer
+   */
+  CRTC_SET_POST_PROC,
+  /*
+   * Op: Sets CRTC ROIs.
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - number of ROIs
+   *      DRMRect * - Array of CRTC ROIs
+   */
+  CRTC_SET_ROI,
+  /*
+   * Op: Returns retire fence for this commit. Should be called after Commit() on
+   * DRMAtomicReqInterface.
+   * Arg: uint32_t - Connector ID
+   *      int * - Pointer to an integer that will hold the returned fence
+   */
+  CONNECTOR_GET_RETIRE_FENCE,
+  /*
+   * Op: Sets writeback connector destination rect
+   * Arg: uint32_t - Connector ID
+   *      DRMRect - Dst Rectangle
+   */
+  CONNECTOR_SET_OUTPUT_RECT,
+  /*
+   * Op: Sets frame buffer ID for writeback connector.
+   * Arg: uint32_t - Connector ID
+   *      uint32_t - Framebuffer ID
+   */
+  CONNECTOR_SET_OUTPUT_FB_ID,
+  /*
+   * Op: Sets power mode for connector.
+   * Arg: uint32_t - Connector ID
+   *      uint32_t - Power Mode
+   */
+  CONNECTOR_SET_POWER_MODE,
+  /*
+   * Op: Sets panel ROIs.
+   * Arg: uint32_t - Connector ID
+   *      uint32_t - number of ROIs
+   *      DRMRect * - Array of Connector ROIs
+   */
+  CONNECTOR_SET_ROI,
+};
+
+enum struct DRMRotation {
+  FLIP_H = 0x1,
+  FLIP_V = 0x2,
+  ROT_180 = FLIP_H | FLIP_V,
+  ROT_90 = 0x4,
+};
+
+enum struct DRMPowerMode {
+  ON,
+  DOZE,
+  DOZE_SUSPEND,
+  OFF,
+};
+
+enum struct DRMBlendType {
+  UNDEFINED = 0,
+  OPAQUE = 1,
+  PREMULTIPLIED = 2,
+  COVERAGE = 3,
+};
+
+enum struct DRMSrcConfig {
+  DEINTERLACE = 0,
+};
+
+/* Display type to identify a suitable connector */
+enum struct DRMDisplayType {
+  PERIPHERAL,
+  TV,
+  VIRTUAL,
+};
+
+struct DRMRect {
+  uint32_t left;    // Left-most pixel coordinate.
+  uint32_t top;     // Top-most pixel coordinate.
+  uint32_t right;   // Right-most pixel coordinate.
+  uint32_t bottom;  // Bottom-most pixel coordinate.
+};
+
+//------------------------------------------------------------------------
+// DRM Info Query Types
+//------------------------------------------------------------------------
+
+enum struct QSEEDVersion {
+  V1,
+  V2,
+  V3,
+};
+
+enum struct SmartDMARevision {
+  V1,
+  V2,
+};
+
+/* Per CRTC Resource Info*/
+struct DRMCrtcInfo {
+  bool has_src_split;
+  uint32_t max_blend_stages;
+  QSEEDVersion qseed_version;
+  SmartDMARevision smart_dma_rev;
+  float ib_fudge_factor;
+  float clk_fudge_factor;
+  uint32_t dest_scale_prefill_lines;
+  uint32_t undersized_prefill_lines;
+  uint32_t macrotile_prefill_lines;
+  uint32_t nv12_prefill_lines;
+  uint32_t linear_prefill_lines;
+  uint32_t downscale_prefill_lines;
+  uint32_t extra_prefill_lines;
+  uint32_t amortized_threshold;
+  uint64_t max_bandwidth_low;
+  uint64_t max_bandwidth_high;
+  uint32_t max_sde_clk;
+  CompRatioMap comp_ratio_rt_map;
+  CompRatioMap comp_ratio_nrt_map;
+};
+
+enum struct DRMPlaneType {
+  // Has CSC and scaling capability
+  VIG = 0,
+  // Has scaling capability but no CSC
+  RGB,
+  // No scaling support
+  DMA,
+  // Supports a small dimension and doesn't use a CRTC stage
+  CURSOR,
+  MAX,
+};
+
+struct DRMPlaneTypeInfo {
+  DRMPlaneType type;
+  uint32_t master_plane_id;
+  // FourCC format enum and modifier
+  std::vector<std::pair<uint32_t, uint64_t>> formats_supported;
+  uint32_t max_linewidth;
+  uint32_t max_upscale;
+  uint32_t max_downscale;
+  uint32_t max_horizontal_deci;
+  uint32_t max_vertical_deci;
+  uint64_t max_pipe_bandwidth;
+};
+
+// All DRM Planes as map<Plane_id , plane_type_info> listed from highest to lowest priority
+typedef std::vector<std::pair<uint32_t, DRMPlaneTypeInfo>>  DRMPlanesInfo;
+
+enum struct DRMTopology {
+  UNKNOWN,  // To be compat with driver defs in sde_kms.h
+  SINGLE_LM,
+  DUAL_LM,
+  PPSPLIT,
+  DUAL_LM_MERGE,
+};
+
+enum struct DRMPanelMode {
+  VIDEO,
+  COMMAND,
+};
+
+/* Per Connector Info*/
+struct DRMConnectorInfo {
+  uint32_t mmWidth;
+  uint32_t mmHeight;
+  uint32_t type;
+  uint32_t num_modes;
+  drmModeModeInfo *modes;
+  DRMTopology topology;
+  std::string panel_name;
+  DRMPanelMode panel_mode;
+  bool is_primary;
+  // Valid only if DRMPanelMode is VIDEO
+  bool dynamic_fps;
+  // FourCC format enum and modifier
+  std::vector<std::pair<uint32_t, uint64_t>> formats_supported;
+  // Valid only if type is DRM_MODE_CONNECTOR_VIRTUAL
+  uint32_t max_linewidth;
+  // Valid only if mode is command
+  int num_roi;
+  int xstart;
+  int ystart;
+  int walign;
+  int halign;
+  int wmin;
+  int hmin;
+  bool roi_merge;
+  DRMRotation panel_orientation;
+};
+
+/* Identifier token for a display */
+struct DRMDisplayToken {
+  uint32_t conn_id;
+  uint32_t crtc_id;
+};
+
+enum DRMPPFeatureID {
+  kFeaturePcc,
+  kFeatureIgc,
+  kFeaturePgc,
+  kFeatureMixerGc,
+  kFeaturePaV2,
+  kFeatureDither,
+  kFeatureGamut,
+  kFeaturePADither,
+  kPPFeaturesMax,
+};
+
+enum DRMPPPropType {
+  kPropEnum,
+  kPropRange,
+  kPropBlob,
+  kPropTypeMax,
+};
+
+struct DRMPPFeatureInfo {
+  DRMPPFeatureID id;
+  DRMPPPropType type;
+  uint32_t version;
+  uint32_t payload_size;
+  void *payload;
+};
+
+struct DRMScalerLUTInfo {
+  uint32_t dir_lut_size = 0;
+  uint32_t cir_lut_size = 0;
+  uint32_t sep_lut_size = 0;
+  uint64_t dir_lut = 0;
+  uint64_t cir_lut = 0;
+  uint64_t sep_lut = 0;
+};
+
+/* DRM Atomic Request Property Set.
+ *
+ * Helper class to create and populate atomic properties of DRM components
+ * when rendered in DRM atomic mode */
+class DRMAtomicReqInterface {
+ public:
+  virtual ~DRMAtomicReqInterface() {}
+  /* Perform request operation.
+   *
+   * [input]: opcode: operation code from DRMOps list.
+   *          var_arg: arguments for DRMOps's can differ in number and
+   *          data type. Refer above DRMOps to details.
+   * [return]: Error code if the API fails, 0 on success.
+   */
+  virtual int Perform(DRMOps opcode, ...) = 0;
+
+  /*
+   * Commit the params set via Perform(). Also resets the properties after commit. Needs to be
+   * called every frame.
+   * [input]: synchronous: Determines if the call should block until a h/w flip
+   * [return]: Error code if the API fails, 0 on success.
+   */
+  virtual int Commit(bool synchronous) = 0;
+  /*
+   * Validate the params set via Perform().
+   * [return]: Error code if the API fails, 0 on success.
+   */
+  virtual int Validate() = 0;
+};
+
+class DRMManagerInterface;
+
+/* Populates a singleton instance of DRMManager */
+typedef int (*GetDRMManager)(int fd, DRMManagerInterface **intf);
+
+/* Destroy DRMManager instance */
+typedef int (*DestroyDRMManager)();
+
+/*
+ * DRM Manager Interface - Any class which plans to implement helper function for vendor
+ * specific DRM driver implementation must implement the below interface routines to work
+ * with SDM.
+ */
+
+class DRMManagerInterface {
+ public:
+  virtual ~DRMManagerInterface() {}
+
+  /*
+   * Since SDM completely manages the planes. GetPlanesInfo will provide all
+   * the plane information.
+   * [output]: DRMPlanesInfo: Resource Info for planes.
+   */
+  virtual void GetPlanesInfo(DRMPlanesInfo *info) = 0;
+
+  /*
+   * Will provide all the information of a selected crtc.
+   * [input]: Use crtc id 0 to obtain system wide info
+   * [output]: DRMCrtcInfo: Resource Info for the given CRTC id.
+   */
+  virtual void GetCrtcInfo(uint32_t crtc_id, DRMCrtcInfo *info) = 0;
+
+  /*
+   * Will provide all the information of a selected connector.
+   * [output]: DRMConnectorInfo: Resource Info for the given connector id
+   */
+  virtual void GetConnectorInfo(uint32_t conn_id, DRMConnectorInfo *info) = 0;
+
+  /*
+   * Will query post propcessing feature info of a CRTC.
+   * [output]: DRMPPFeatureInfo: CRTC post processing feature info
+   */
+  virtual void GetCrtcPPInfo(uint32_t crtc_id, DRMPPFeatureInfo &info) = 0;
+  /*
+   * Register a logical display to receive a token.
+   * Each display pipeline in DRM is identified by its CRTC and Connector(s).
+   * On display connect(bootup or hotplug), clients should invoke this interface to
+   * establish the pipeline for the display and should get a DisplayToken
+   * populated with crtc and connnector(s) id's. Here onwards, Client should
+   * use this token to represent the display for any Perform operations if
+   * needed.
+   *
+   * [input]: disp_type - Peripheral / TV / Virtual
+   * [output]: DRMDisplayToken - CRTC and Connector id's for the display
+   * [return]: 0 on success, a negative error value otherwise
+   */
+  virtual int RegisterDisplay(DRMDisplayType disp_type, DRMDisplayToken *tok) = 0;
+
+  /* Client should invoke this interface on display disconnect.
+   * [input]: DRMDisplayToken - identifier for the display.
+   */
+  virtual void UnregisterDisplay(const DRMDisplayToken &token) = 0;
+
+  /*
+   * Creates and returns an instance of DRMAtomicReqInterface corresponding to a display token
+   * returned as part of RegisterDisplay API. Needs to be called per display.
+   * [input]: DRMDisplayToken that identifies a display pipeline
+   * [output]: Pointer to an instance of DRMAtomicReqInterface.
+   * [return]: Error code if the API fails, 0 on success.
+   */
+  virtual int CreateAtomicReq(const DRMDisplayToken &token, DRMAtomicReqInterface **intf) = 0;
+
+  /*
+   * Destroys the instance of DRMAtomicReqInterface
+   * [input]: Pointer to a DRMAtomicReqInterface
+   * [return]: Error code if the API fails, 0 on success.
+   */
+  virtual int DestroyAtomicReq(DRMAtomicReqInterface *intf) = 0;
+  /*
+   * Sets the global scaler LUT
+   * [input]: LUT Info
+   * [return]: Error code if the API fails, 0 on success.
+   */
+  virtual int SetScalerLUT(const DRMScalerLUTInfo &lut_info) = 0;
+};
+
+}  // namespace sde_drm
+#endif  // __DRM_INTERFACE_H__
diff --git a/sdm845/libdrmutils/drm_lib_loader.cpp b/sdm845/libdrmutils/drm_lib_loader.cpp
new file mode 100644
index 0000000..83c9f1b
--- /dev/null
+++ b/sdm845/libdrmutils/drm_lib_loader.cpp
@@ -0,0 +1,92 @@
+/*
+* Copyright (c) 2017, 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 "drm_lib_loader.h"
+
+#define __CLASS__ "DRMLibLoader"
+
+using std::mutex;
+using std::lock_guard;
+
+namespace drm_utils {
+
+DRMLibLoader *DRMLibLoader::s_instance = nullptr;
+mutex DRMLibLoader::s_lock;
+
+DRMLibLoader *DRMLibLoader::GetInstance() {
+  lock_guard<mutex> obj(s_lock);
+
+  if (!s_instance) {
+    s_instance = new DRMLibLoader();
+  }
+
+  return s_instance;
+}
+
+void DRMLibLoader::Destroy() {
+  lock_guard<mutex> obj(s_lock);
+  if (s_instance) {
+    delete s_instance;
+    s_instance = nullptr;
+  }
+}
+
+DRMLibLoader::DRMLibLoader() {
+  if (Open("libsdedrm.so")) {
+    if (Sym("GetDRMManager", reinterpret_cast<void **>(&func_get_drm_manager_)) &&
+        Sym("DestroyDRMManager", reinterpret_cast<void **>(&func_destroy_drm_manager_))) {
+      is_loaded_ = true;
+    }
+  }
+}
+
+DRMLibLoader::~DRMLibLoader() {
+  if (lib_) {
+    ::dlclose(lib_);
+    lib_ = nullptr;
+  }
+}
+
+bool DRMLibLoader::Open(const char *lib_name) {
+  lib_ = ::dlopen(lib_name, RTLD_NOW);
+
+  return (lib_ != nullptr);
+}
+
+bool DRMLibLoader::Sym(const char *func_name, void **func_ptr) {
+  if (lib_) {
+    *func_ptr = ::dlsym(lib_, func_name);
+  }
+
+  return (*func_ptr != nullptr);
+}
+
+}  // namespace drm_utils
diff --git a/sdm845/libdrmutils/drm_lib_loader.h b/sdm845/libdrmutils/drm_lib_loader.h
new file mode 100644
index 0000000..d132d69
--- /dev/null
+++ b/sdm845/libdrmutils/drm_lib_loader.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2017, 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 __DRM_LIB_LOADER_H__
+#define __DRM_LIB_LOADER_H__
+
+#include <drm_interface.h>
+#include <mutex>
+
+namespace drm_utils {
+
+class DRMLibLoader {
+ public:
+  ~DRMLibLoader();
+  bool IsLoaded() { return is_loaded_; }
+  sde_drm::GetDRMManager FuncGetDRMManager() { return func_get_drm_manager_; }
+  sde_drm::DestroyDRMManager FuncDestroyDRMManager() { return func_destroy_drm_manager_; }
+
+  static DRMLibLoader *GetInstance();
+  static void Destroy();
+
+ private:
+  DRMLibLoader();
+  bool Open(const char *lib_name);
+  bool Sym(const char *func_name, void **func_ptr);
+
+  void *lib_ = {};
+  sde_drm::GetDRMManager func_get_drm_manager_ = {};
+  sde_drm::DestroyDRMManager func_destroy_drm_manager_ = {};
+  bool is_loaded_ = false;
+
+  static DRMLibLoader *s_instance;  // Singleton instance
+  static std::mutex s_lock;
+};
+
+}  // namespace drm_utils
+
+#endif  // __DRM_LIB_LOADER_H__
diff --git a/sdm845/libdrmutils/drm_logger.h b/sdm845/libdrmutils/drm_logger.h
new file mode 100644
index 0000000..d0b0773
--- /dev/null
+++ b/sdm845/libdrmutils/drm_logger.h
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2017, 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 __DRM_LOGGER_H__
+#define __DRM_LOGGER_H__
+
+#include <utility>
+
+namespace drm_utils {
+
+class DRMLogger {
+ public:
+  virtual ~DRMLogger() {}
+  virtual void Error(const char *format, ...) = 0;
+  virtual void Warning(const char *format, ...) = 0;
+  virtual void Info(const char *format, ...) = 0;
+  virtual void Debug(const char *format, ...) = 0;
+
+  static void Set(DRMLogger *logger) { s_instance = logger; }
+  static DRMLogger *Get() { return s_instance; }
+
+ private:
+  static DRMLogger *s_instance;
+};
+
+#define DRM_LOG(method, format, ...)                            \
+  if (drm_utils::DRMLogger::Get()) {                            \
+    drm_utils::DRMLogger::Get()->method(format, ##__VA_ARGS__); \
+  }
+
+#define DRM_LOG_CONTEXT(method, format, ...) \
+  DRM_LOG(method, __CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__);
+
+#define DRM_LOGE(format, ...) DRM_LOG_CONTEXT(Error, format, ##__VA_ARGS__)
+#define DRM_LOGW(format, ...) DRM_LOG_CONTEXT(Warning, format, ##__VA_ARGS__)
+#define DRM_LOGI(format, ...) DRM_LOG_CONTEXT(Info, format, ##__VA_ARGS__)
+#define DRM_LOGD_IF(pred, format, ...) \
+  if (pred)                            \
+  DRM_LOG_CONTEXT(Debug, format, ##__VA_ARGS__)
+
+}  // namespace drm_utils
+
+#endif  // __DRM_LOGGER_H__
diff --git a/sdm845/libdrmutils/drm_master.cpp b/sdm845/libdrmutils/drm_master.cpp
new file mode 100644
index 0000000..09e0729
--- /dev/null
+++ b/sdm845/libdrmutils/drm_master.cpp
@@ -0,0 +1,149 @@
+/*
+* Copyright (c) 2017, 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 <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+// Intentionally included after xf86 headers so that they in-turn include libdrm version of drm.h
+// that doesn't use keyword "virtual" for a variable name. Not doing so leads to the kernel version
+// of drm.h being included causing compilation to fail
+#include <drm/msm_drm.h>
+#include <algorithm>
+#include <iterator>
+
+#include "drm_master.h"
+
+#define __CLASS__ "DRMMaster"
+
+using std::mutex;
+using std::lock_guard;
+using std::begin;
+using std::copy;
+using std::end;
+using std::fill;
+
+namespace drm_utils {
+
+DRMLogger *DRMLogger::s_instance = nullptr;
+DRMMaster *DRMMaster::s_instance = nullptr;
+mutex DRMMaster::s_lock;
+
+int DRMMaster::GetInstance(DRMMaster **master) {
+  lock_guard<mutex> obj(s_lock);
+
+  if (!s_instance) {
+    s_instance = new DRMMaster();
+    if (s_instance->Init() < 0) {
+      delete s_instance;
+      s_instance = nullptr;
+      return -ENODEV;
+    }
+  }
+
+  *master = s_instance;
+  return 0;
+}
+
+void DRMMaster::DestroyInstance() {
+  lock_guard<mutex> obj(s_lock);
+  delete s_instance;
+  s_instance = nullptr;
+}
+
+int DRMMaster::Init() {
+  dev_fd_ = drmOpen("msm_drm", nullptr);
+  if (dev_fd_ < 0) {
+    DRM_LOGE("drmOpen failed with error %d", dev_fd_);
+    return -ENODEV;
+  }
+
+  return 0;
+}
+
+DRMMaster::~DRMMaster() {
+  drmClose(dev_fd_);
+  dev_fd_ = -1;
+}
+
+int DRMMaster::CreateFbId(const DRMBuffer &drm_buffer, uint32_t *fb_id) {
+  uint32_t gem_handle = 0;
+  int ret = drmPrimeFDToHandle(dev_fd_, drm_buffer.fd, &gem_handle);
+  if (ret) {
+    DRM_LOGE("drmPrimeFDToHandle failed with error %d", ret);
+    return ret;
+  }
+
+  struct drm_mode_fb_cmd2 cmd2 {};
+  cmd2.width = drm_buffer.width;
+  cmd2.height = drm_buffer.height;
+  cmd2.pixel_format = drm_buffer.drm_format;
+  cmd2.flags = DRM_MODE_FB_MODIFIERS;
+  fill(begin(cmd2.handles), begin(cmd2.handles) + drm_buffer.num_planes, gem_handle);
+  copy(begin(drm_buffer.stride), end(drm_buffer.stride), begin(cmd2.pitches));
+  copy(begin(drm_buffer.offset), end(drm_buffer.offset), begin(cmd2.offsets));
+  fill(begin(cmd2.modifier), begin(cmd2.modifier) + drm_buffer.num_planes,
+       drm_buffer.drm_format_modifier);
+
+  if ((ret = drmIoctl(dev_fd_, DRM_IOCTL_MODE_ADDFB2, &cmd2))) {
+    DRM_LOGE("DRM_IOCTL_MODE_ADDFB2 failed with error %d", ret);
+  } else {
+    *fb_id = cmd2.fb_id;
+  }
+
+  struct drm_gem_close gem_close = {};
+  gem_close.handle = gem_handle;
+  int ret1 = drmIoctl(dev_fd_, DRM_IOCTL_GEM_CLOSE, &gem_close);
+  if (ret1) {
+    DRM_LOGE("drmIoctl::DRM_IOCTL_GEM_CLOSE failed with error %d", ret1);
+    return ret1;
+  }
+
+  return ret;
+}
+
+int DRMMaster::RemoveFbId(uint32_t fb_id) {
+  int ret = 0;
+#ifdef DRM_IOCTL_MSM_RMFB2
+  ret = drmIoctl(dev_fd_, DRM_IOCTL_MSM_RMFB2, &fb_id);
+  if (ret) {
+    DRM_LOGE("drmIoctl::DRM_IOCTL_MSM_RMFB2 failed for fb_id %d with error %d", fb_id, errno);
+  }
+#else
+  ret = drmModeRmFB(dev_fd_, fb_id);
+  if (ret) {
+    DRM_LOGE("drmModeRmFB failed for fb_id %d with error %d", fb_id, ret);
+  }
+#endif
+  return ret;
+}
+
+}  // namespace drm_utils
diff --git a/sdm845/libdrmutils/drm_master.h b/sdm845/libdrmutils/drm_master.h
new file mode 100644
index 0000000..52a8b02
--- /dev/null
+++ b/sdm845/libdrmutils/drm_master.h
@@ -0,0 +1,95 @@
+/*
+* Copyright (c) 2017, 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 __DRM_MASTER_H__
+#define __DRM_MASTER_H__
+
+#include <mutex>
+
+#include "drm_logger.h"
+
+namespace drm_utils {
+
+struct DRMBuffer {
+  int fd = -1;
+  uint32_t width = 0;
+  uint32_t height = 0;
+  uint32_t drm_format = 0;
+  uint64_t drm_format_modifier = 0;
+  uint32_t stride[4] = {};
+  uint32_t offset[4] = {};
+  uint32_t num_planes = 1;
+};
+
+class DRMMaster {
+ public:
+  ~DRMMaster();
+  /* Converts from ION fd --> Prime Handle --> FB_ID.
+   * Input:
+   *   drm_buffer: A DRMBuffer obj that packages description of buffer
+   * Output:
+   *   fb_id: Pointer to store DRM framebuffer id into
+   * Returns:
+   *   ioctl error code
+   */
+  int CreateFbId(const DRMBuffer &drm_buffer, uint32_t *fb_id);
+  /* Removes the fb_id from DRM
+   * Input:
+   *   fb_id: DRM FB to be removed
+   * Returns:
+   *   ioctl error code
+   */
+  int RemoveFbId(uint32_t fb_id);
+  /* Poplulates master DRM fd
+   * Input:
+   *   fd: Pointer to store master fd into
+   */
+  void GetHandle(int *fd) { *fd = dev_fd_; }
+
+  /* Creates an instance of DRMMaster if it doesn't exist and initializes it. Threadsafe.
+   * Input:
+   *   master: Pointer to store a pointer to the instance
+   * Returns:
+   *   -ENODEV if device cannot be opened or initilization fails
+   */
+  static int GetInstance(DRMMaster **master);
+  static void DestroyInstance();
+
+ private:
+  DRMMaster() {}
+  int Init();
+
+  int dev_fd_ = -1;              // Master fd for DRM
+  static DRMMaster *s_instance;  // Singleton instance
+  static std::mutex s_lock;
+};
+
+}  // namespace drm_utils
+
+#endif  // __DRM_MASTER_H__
diff --git a/sdm845/libdrmutils/drm_res_mgr.cpp b/sdm845/libdrmutils/drm_res_mgr.cpp
new file mode 100644
index 0000000..1d29495
--- /dev/null
+++ b/sdm845/libdrmutils/drm_res_mgr.cpp
@@ -0,0 +1,151 @@
+/*
+* Copyright (c) 2017, 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 <errno.h>
+
+#include "drm_master.h"
+#include "drm_res_mgr.h"
+
+#define DEBUG 0
+#define __CLASS__ "DRMResMgr"
+
+using std::mutex;
+using std::lock_guard;
+
+namespace drm_utils {
+
+DRMResMgr *DRMResMgr::s_instance = nullptr;
+mutex DRMResMgr::s_lock;
+
+static bool GetConnector(int dev_fd, drmModeRes *res, drmModeConnector **connector) {
+  for (auto i = 0; i < res->count_connectors; i++) {
+    drmModeConnector *conn = drmModeGetConnector(dev_fd, res->connectors[i]);
+    if (conn && conn->connector_type == DRM_MODE_CONNECTOR_DSI && conn->count_modes &&
+        conn->connection == DRM_MODE_CONNECTED) {
+      *connector = conn;
+      DRM_LOGI("Found connector %d", conn->connector_id);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+static bool GetEncoder(int dev_fd, drmModeConnector *conn, drmModeEncoder **encoder) {
+  for (auto i = 0; i < conn->count_encoders; i++) {
+    drmModeEncoder *enc = drmModeGetEncoder(dev_fd, conn->encoders[i]);
+    if (enc && enc->encoder_type == DRM_MODE_ENCODER_DSI) {
+      *encoder = enc;
+      DRM_LOGI("Found encoder %d", enc->encoder_id);
+      return true;
+    }
+  }
+  return false;
+}
+
+static bool GetCrtc(int dev_fd, drmModeRes *res, drmModeEncoder *enc, drmModeCrtc **crtc) {
+  for (auto i = 0; i < res->count_crtcs; i++) {
+    if (enc->possible_crtcs & (1 << i)) {
+      drmModeCrtc *c = drmModeGetCrtc(dev_fd, res->crtcs[i]);
+      if (c) {
+        *crtc = c;
+        DRM_LOGI("Found crtc %d", c->crtc_id);
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+#define __CLASS__ "DRMResMgr"
+
+int DRMResMgr::GetInstance(DRMResMgr **res_mgr) {
+  lock_guard<mutex> obj(s_lock);
+
+  if (!s_instance) {
+    s_instance = new DRMResMgr();
+    if (s_instance->Init() < 0) {
+      delete s_instance;
+      s_instance = nullptr;
+      return -ENODEV;
+    }
+  }
+
+  *res_mgr = s_instance;
+  return 0;
+}
+
+int DRMResMgr::Init() {
+  DRMMaster *master = nullptr;
+  int dev_fd = -1;
+
+  int ret = DRMMaster::GetInstance(&master);
+  if (ret < 0) {
+    return ret;
+  }
+
+  master->GetHandle(&dev_fd);
+  drmModeRes *res = drmModeGetResources(dev_fd);
+  if (res == nullptr) {
+    DRM_LOGE("drmModeGetResources failed");
+    return -ENODEV;
+  }
+
+  drmModeConnector *conn = nullptr;
+  if (!GetConnector(dev_fd, res, &conn)) {
+    DRM_LOGE("Failed to find a connector");
+    return -ENODEV;
+  }
+
+  drmModeEncoder *enc = nullptr;
+  if (!GetEncoder(dev_fd, conn, &enc)) {
+    DRM_LOGE("Failed to find an encoder");
+    drmModeFreeConnector(conn);
+    return -ENODEV;
+  }
+
+  drmModeCrtc *crtc = nullptr;
+  if (!GetCrtc(dev_fd, res, enc, &crtc)) {
+    DRM_LOGE("Failed to find a crtc");
+    drmModeFreeEncoder(enc);
+    drmModeFreeConnector(conn);
+    drmModeFreeResources(res);
+    return -ENODEV;
+  }
+
+  res_ = res;
+  conn_ = conn;
+  enc_ = enc;
+  crtc_ = crtc;
+
+  return 0;
+}
+
+}  // namespace drm_utils
diff --git a/sdm845/libdrmutils/drm_res_mgr.h b/sdm845/libdrmutils/drm_res_mgr.h
new file mode 100644
index 0000000..3a8378c
--- /dev/null
+++ b/sdm845/libdrmutils/drm_res_mgr.h
@@ -0,0 +1,72 @@
+/*
+* Copyright (c) 2017, 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 __DRM_RES_MGR_H__
+#define __DRM_RES_MGR_H__
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <mutex>
+
+namespace drm_utils {
+
+class DRMResMgr {
+ public:
+  /* Returns the default connector id for primary panel */
+  void GetConnectorId(uint32_t *id) { *id = conn_->connector_id; }
+  /* Returns the default crtc id for primary pipeline */
+  void GetCrtcId(uint32_t *id) { *id = crtc_->crtc_id; }
+  /* Returns the default mode currently used by the connector */
+  void GetMode(drmModeModeInfo *mode) { *mode = conn_->modes[0]; }
+  /* Returns the panel dimensions in mm */
+  void GetDisplayDimInMM(uint32_t *w, uint32_t *h) {
+    *w = conn_->mmWidth;
+    *h = conn_->mmHeight;
+  }
+
+  /* Creates and initializes an instance of DRMResMgr. On success, returns a pointer to it, on
+   * failure returns -ENODEV */
+  static int GetInstance(DRMResMgr **res_mgr);
+
+ private:
+  int Init();
+
+  drmModeRes *res_ = nullptr;
+  drmModeConnector *conn_ = nullptr;
+  drmModeEncoder *enc_ = nullptr;
+  drmModeCrtc *crtc_ = nullptr;
+
+  static DRMResMgr *s_instance;
+  static std::mutex s_lock;
+};
+
+}  // namespace drm_utils
+
+#endif  // __DRM_RES_MGR_H__
diff --git a/sdm845/libgralloc/Android.mk b/sdm845/libgralloc/Android.mk
new file mode 100644
index 0000000..86c0f04
--- /dev/null
+++ b/sdm845/libgralloc/Android.mk
@@ -0,0 +1,52 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Gralloc module
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := gralloc.$(TARGET_BOARD_PLATFORM)
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_RELATIVE_PATH    := hw
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_HEADER_LIBRARIES        := display_headers
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libmemalloc libqdMetaData libqdutils
+ifneq ($(TARGET_IS_HEADLESS), true)
+LOCAL_SHARED_LIBRARIES        += libGLESv1_CM
+endif
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wno-sign-conversion
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
+LOCAL_SRC_FILES               := gpu.cpp gralloc.cpp framebuffer.cpp mapper.cpp
+LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
+LOCAL_COPY_HEADERS            := gralloc_priv.h gr.h adreno_utils.h
+
+include $(BUILD_SHARED_LIBRARY)
+
+# MemAlloc Library
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := libmemalloc
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_HEADER_LIBRARIES        := display_headers
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdutils libdl
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdmemalloc\" -Wno-sign-conversion
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
+LOCAL_SRC_FILES               := ionalloc.cpp alloc_controller.cpp
+LOCAL_COPY_HEADERS            := alloc_controller.h memalloc.h
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/sdm845/libgralloc/MODULE_LICENSE_APACHE2 b/sdm845/libgralloc/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sdm845/libgralloc/MODULE_LICENSE_APACHE2
diff --git a/sdm845/libgralloc/Makefile.am b/sdm845/libgralloc/Makefile.am
new file mode 100644
index 0000000..3cf3960
--- /dev/null
+++ b/sdm845/libgralloc/Makefile.am
@@ -0,0 +1,42 @@
+HEADER_PATH := ${WORKSPACE}/display/display-hal/include
+h_sources = alloc_controller.h \
+            memalloc.h
+
+cpp_sources = ionalloc.cpp \
+              alloc_controller.cpp
+
+memalloc_includedir = $(pkgincludedir)
+memalloc_include_HEADERS = $(h_sources)
+
+lib_LTLIBRARIES = libmemalloc.la
+libmemalloc_la_CC = @CC@
+libmemalloc_la_SOURCES = $(cpp_sources)
+libmemalloc_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"qdmemalloc\"
+libmemalloc_la_CPPFLAGS = $(AM_CPPFLAGS)
+libmemalloc_la_LIBADD = ../libqdutils/libqdutils.la
+libmemalloc_la_LIBADD += -lhardware -lcutils -llog -lutils -ldl
+libmemalloc_la_LDFLAGS = -shared -avoid-version
+
+header_sources = gralloc_priv.h \
+                 gr.h \
+                 adreno_utils.h \
+                 $(HEADER_PATH)/color_metadata.h
+
+c_sources = gpu.cpp \
+            gralloc.cpp \
+            framebuffer.cpp \
+            mapper.cpp
+
+library_includedir = $(pkgincludedir)
+library_include_HEADERS = $(header_sources)
+
+lib_LTLIBRARIES += libgralloc.la
+libgralloc_la_CC = @CC@
+libgralloc_la_SOURCES = $(c_sources)
+libgralloc_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"qdgralloc\"
+libgralloc_la_CPPFLAGS = $(AM_CPPFLAGS)
+libgralloc_la_LIBADD = ../libqdutils/libqdutils.la
+libgralloc_la_LIBADD += ../libqdutils/libqdMetaData.la
+libgralloc_la_LIBADD += -lhardware -lcutils -llog -lutils -lbinder
+libgralloc_la_LIBADD += libmemalloc.la
+libgralloc_la_LDFLAGS = -shared -avoid-version
diff --git a/sdm845/libgralloc/NOTICE b/sdm845/libgralloc/NOTICE
new file mode 100644
index 0000000..3237da6
--- /dev/null
+++ b/sdm845/libgralloc/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2008-2009, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/sdm845/libgralloc/adreno_utils.h b/sdm845/libgralloc/adreno_utils.h
new file mode 100644
index 0000000..baecef9
--- /dev/null
+++ b/sdm845/libgralloc/adreno_utils.h
@@ -0,0 +1,59 @@
+/*
+* Copyright (c) 2015 - 2017, 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.
+*/
+
+// Adreno Pixel Formats
+typedef enum {
+
+    ADRENO_PIXELFORMAT_UNKNOWN       = 0,
+    ADRENO_PIXELFORMAT_R10G10B10A2_UNORM = 24,  // Vertex, Normalized GL_UNSIGNED_INT_10_10_10_2_OES
+    ADRENO_PIXELFORMAT_R8G8B8A8      = 28,
+    ADRENO_PIXELFORMAT_R8G8B8A8_SRGB = 29,
+    ADRENO_PIXELFORMAT_B5G6R5        = 85,
+    ADRENO_PIXELFORMAT_B5G5R5A1      = 86,
+    ADRENO_PIXELFORMAT_B8G8R8A8      = 90,
+    ADRENO_PIXELFORMAT_B8G8R8A8_SRGB = 91,
+    ADRENO_PIXELFORMAT_B8G8R8X8_SRGB = 93,
+    ADRENO_PIXELFORMAT_NV12          = 103,
+    ADRENO_PIXELFORMAT_P010          = 104,
+    ADRENO_PIXELFORMAT_YUY2          = 107,
+    ADRENO_PIXELFORMAT_B4G4R4A4      = 115,
+    ADRENO_PIXELFORMAT_NV12_EXT      = 506,  // NV12 with non-std alignment and offsets
+    ADRENO_PIXELFORMAT_R8G8B8X8      = 507,  // GL_RGB8 (Internal)
+    ADRENO_PIXELFORMAT_R8G8B8        = 508,  // GL_RGB8
+    ADRENO_PIXELFORMAT_A1B5G5R5      = 519,  // GL_RGB5_A1
+    ADRENO_PIXELFORMAT_R8G8B8X8_SRGB = 520,  // GL_SRGB8
+    ADRENO_PIXELFORMAT_R8G8B8_SRGB   = 521,  // GL_SRGB8
+    ADRENO_PIXELFORMAT_A2B10G10R10_UNORM = 532,
+                                             // Vertex, Normalized GL_UNSIGNED_INT_10_10_10_2_OES
+    ADRENO_PIXELFORMAT_R10G10B10X2_UNORM = 537,
+                                             // Vertex, Normalized GL_UNSIGNED_INT_10_10_10_2_OES
+    ADRENO_PIXELFORMAT_R5G6B5        = 610,  // RGBA version of B5G6R5
+    ADRENO_PIXELFORMAT_R5G5B5A1      = 611,  // RGBA version of B5G5R5A1
+    ADRENO_PIXELFORMAT_R4G4B4A4      = 612,  // RGBA version of B4G4R4A4
+    ADRENO_PIXELFORMAT_UYVY          = 614,  // YUV 4:2:2 packed progressive (1 plane)
+    ADRENO_PIXELFORMAT_NV21          = 619,
+    ADRENO_PIXELFORMAT_Y8U8V8A8      = 620,  // YUV 4:4:4 packed (1 plane)
+    ADRENO_PIXELFORMAT_Y8            = 625,  // Single 8-bit luma only channel YUV format
+    ADRENO_PIXELFORMAT_TP10          = 654,  // YUV 4:2:0 planar 10 bits/comp (2 planes)
+} ADRENOPIXELFORMAT;
diff --git a/sdm845/libgralloc/alloc_controller.cpp b/sdm845/libgralloc/alloc_controller.cpp
new file mode 100644
index 0000000..d2a522e
--- /dev/null
+++ b/sdm845/libgralloc/alloc_controller.cpp
@@ -0,0 +1,1223 @@
+/*
+ * Copyright (c) 2011 - 2017, 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/log.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <media/msm_media_info.h>
+#include <qdMetaData.h>
+#include <utils/Singleton.h>
+#include <utils/Mutex.h>
+#include <algorithm>
+
+#include "gralloc_priv.h"
+#include "alloc_controller.h"
+#include "memalloc.h"
+#include "ionalloc.h"
+#include "gr.h"
+#include "qd_utils.h"
+
+#define ASTC_BLOCK_SIZE 16
+
+#ifndef ION_FLAG_CP_PIXEL
+#define ION_FLAG_CP_PIXEL 0
+#endif
+
+#ifndef ION_FLAG_ALLOW_NON_CONTIG
+#define ION_FLAG_ALLOW_NON_CONTIG 0
+#endif
+
+#ifndef ION_FLAG_CP_CAMERA_PREVIEW
+#define ION_FLAG_CP_CAMERA_PREVIEW 0
+#endif
+
+#ifdef MASTER_SIDE_CP
+#define CP_HEAP_ID ION_SECURE_HEAP_ID
+#define SD_HEAP_ID ION_SECURE_DISPLAY_HEAP_ID
+#define ION_CP_FLAGS (ION_SECURE | ION_FLAG_CP_PIXEL)
+#define ION_SD_FLAGS (ION_SECURE | ION_FLAG_CP_SEC_DISPLAY)
+#define ION_SC_FLAGS (ION_SECURE | ION_FLAG_CP_CAMERA)
+#define ION_SC_PREVIEW_FLAGS (ION_SECURE | ION_FLAG_CP_CAMERA_PREVIEW)
+#else // SLAVE_SIDE_CP
+#define CP_HEAP_ID ION_CP_MM_HEAP_ID
+#define SD_HEAP_ID CP_HEAP_ID
+#define ION_CP_FLAGS (ION_SECURE | ION_FLAG_ALLOW_NON_CONTIG)
+#define ION_SD_FLAGS ION_SECURE
+#define ION_SC_FLAGS ION_SECURE
+#define ION_SC_PREVIEW_FLAGS ION_SECURE
+#endif
+
+#ifndef COLOR_FMT_P010_UBWC
+#define COLOR_FMT_P010_UBWC 9
+#endif
+
+using namespace gralloc;
+using namespace qdutils;
+using namespace android;
+
+ANDROID_SINGLETON_STATIC_INSTANCE(AdrenoMemInfo);
+ANDROID_SINGLETON_STATIC_INSTANCE(MDPCapabilityInfo);
+
+static void getYuvUBwcWidthHeight(int, int, int, int&, int&);
+static unsigned int getUBwcSize(int, int, int, const int, const int);
+
+//Common functions
+
+/* The default policy is to return cached buffers unless the client explicity
+ * sets the PRIVATE_UNCACHED flag or indicates that the buffer will be rarely
+ * read or written in software. Any combination with a _RARELY_ flag will be
+ * treated as uncached. */
+static bool useUncached(const int& usage) {
+    if ((usage & GRALLOC_USAGE_PROTECTED) or
+        (usage & GRALLOC_USAGE_PRIVATE_UNCACHED) or
+        ((usage & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_RARELY) or
+        ((usage & GRALLOC_USAGE_SW_READ_MASK) ==  GRALLOC_USAGE_SW_READ_RARELY))
+        return true;
+
+    return false;
+}
+
+//------------- MDPCapabilityInfo-----------------------//
+MDPCapabilityInfo :: MDPCapabilityInfo() {
+  qdutils::querySDEInfo(HAS_UBWC, &isUBwcSupported);
+  qdutils::querySDEInfo(HAS_WB_UBWC, &isWBUBWCSupported);
+}
+
+//------------- AdrenoMemInfo-----------------------//
+AdrenoMemInfo::AdrenoMemInfo()
+{
+    LINK_adreno_compute_aligned_width_and_height = NULL;
+    LINK_adreno_compute_padding = NULL;
+    LINK_adreno_compute_compressedfmt_aligned_width_and_height = NULL;
+    LINK_adreno_isUBWCSupportedByGpu = NULL;
+    LINK_adreno_get_gpu_pixel_alignment = NULL;
+
+    libadreno_utils = ::dlopen("libadreno_utils.so", RTLD_NOW);
+    if (libadreno_utils) {
+        *(void **)&LINK_adreno_compute_aligned_width_and_height =
+                ::dlsym(libadreno_utils, "compute_aligned_width_and_height");
+        *(void **)&LINK_adreno_compute_padding =
+                ::dlsym(libadreno_utils, "compute_surface_padding");
+        *(void **)&LINK_adreno_compute_compressedfmt_aligned_width_and_height =
+                ::dlsym(libadreno_utils,
+                        "compute_compressedfmt_aligned_width_and_height");
+        *(void **)&LINK_adreno_isUBWCSupportedByGpu =
+                ::dlsym(libadreno_utils, "isUBWCSupportedByGpu");
+        *(void **)&LINK_adreno_get_gpu_pixel_alignment =
+                ::dlsym(libadreno_utils, "get_gpu_pixel_alignment");
+    }
+
+    // Check if the overriding property debug.gralloc.gfx_ubwc_disable
+    // that disables UBWC allocations for the graphics stack is set
+    gfx_ubwc_disable = 0;
+    char property[PROPERTY_VALUE_MAX];
+    property_get("debug.gralloc.gfx_ubwc_disable", property, "0");
+    if(!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
+       !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
+        gfx_ubwc_disable = 1;
+    }
+}
+
+AdrenoMemInfo::~AdrenoMemInfo()
+{
+    if (libadreno_utils) {
+        ::dlclose(libadreno_utils);
+    }
+}
+
+void AdrenoMemInfo::getAlignedWidthAndHeight(const private_handle_t *hnd, int& aligned_w,
+                          int& aligned_h) {
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+    if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+        int w = metadata->bufferDim.sliceWidth;
+        int h = metadata->bufferDim.sliceHeight;
+        int f = hnd->format;
+        int usage = 0;
+
+        if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+            usage = GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+        }
+
+        getAlignedWidthAndHeight(w, h, f, usage, aligned_w, aligned_h);
+    } else {
+        aligned_w = hnd->width;
+        aligned_h = hnd->height;
+    }
+
+}
+
+void AdrenoMemInfo::getUnalignedWidthAndHeight(const private_handle_t *hnd, int& unaligned_w,
+                                               int& unaligned_h) {
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+    if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+        unaligned_w = metadata->bufferDim.sliceWidth;
+        unaligned_h = metadata->bufferDim.sliceHeight;
+    } else {
+        unaligned_w = hnd->unaligned_width;
+        unaligned_h = hnd->unaligned_height;
+    }
+}
+
+bool isUncompressedRgbFormat(int format)
+{
+    bool is_rgb_format = false;
+
+    switch (format)
+    {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGB_888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444:
+        case HAL_PIXEL_FORMAT_R_8:
+        case HAL_PIXEL_FORMAT_RG_88:
+        case HAL_PIXEL_FORMAT_BGRX_8888:
+        case HAL_PIXEL_FORMAT_BGR_888:
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
+        case HAL_PIXEL_FORMAT_ARGB_2101010:
+        case HAL_PIXEL_FORMAT_RGBX_1010102:
+        case HAL_PIXEL_FORMAT_XRGB_2101010:
+        case HAL_PIXEL_FORMAT_BGRA_1010102:
+        case HAL_PIXEL_FORMAT_ABGR_2101010:
+        case HAL_PIXEL_FORMAT_BGRX_1010102:
+        case HAL_PIXEL_FORMAT_XBGR_2101010:    // Intentional fallthrough
+            is_rgb_format = true;
+            break;
+        default:
+            break;
+    }
+
+    return is_rgb_format;
+}
+
+void AdrenoMemInfo::getAlignedWidthAndHeight(int width, int height, int format,
+                            int usage, int& aligned_w, int& aligned_h)
+{
+    bool ubwc_enabled = isUBwcEnabled(format, usage);
+
+    // Currently surface padding is only computed for RGB* surfaces.
+    if (isUncompressedRgbFormat(format) == true) {
+        int tileEnabled = ubwc_enabled;
+        getGpuAlignedWidthHeight(width, height, format, tileEnabled, aligned_w, aligned_h);
+    } else if (ubwc_enabled) {
+        getYuvUBwcWidthHeight(width, height, format, aligned_w, aligned_h);
+    } else {
+        aligned_w = width;
+        aligned_h = height;
+        int alignment = 32;
+        switch (format)
+        {
+            case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+                if (LINK_adreno_get_gpu_pixel_alignment) {
+                  alignment = LINK_adreno_get_gpu_pixel_alignment();
+                }
+                aligned_w = ALIGN(width, alignment);
+                break;
+            case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+                aligned_w = ALIGN(width, alignment);
+                break;
+            case HAL_PIXEL_FORMAT_RAW16:
+            case HAL_PIXEL_FORMAT_Y16:
+            case HAL_PIXEL_FORMAT_Y8:
+                aligned_w = ALIGN(width, 16);
+                break;
+            case HAL_PIXEL_FORMAT_RAW12:
+                aligned_w = ALIGN(width * 12 / 8, 8);
+                break;
+            case HAL_PIXEL_FORMAT_RAW10:
+                aligned_w = ALIGN(width * 10 / 8, 8);
+                break;
+            case HAL_PIXEL_FORMAT_RAW8:
+                aligned_w = ALIGN(width, 8);
+                break;
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+                aligned_w = ALIGN(width, 128);
+                break;
+            case HAL_PIXEL_FORMAT_YV12:
+            case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+            case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+            case HAL_PIXEL_FORMAT_YCbCr_422_I:
+            case HAL_PIXEL_FORMAT_YCrCb_422_I:
+            case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+            case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+                aligned_w = ALIGN(width, 16);
+                break;
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+            case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+                aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
+                aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height);
+                break;
+            case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+                aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV21, width);
+                aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV21, height);
+                break;
+            case HAL_PIXEL_FORMAT_BLOB:
+            case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+                break;
+            case HAL_PIXEL_FORMAT_NV21_ZSL:
+                aligned_w = ALIGN(width, 64);
+                aligned_h = ALIGN(height, 64);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+                if(LINK_adreno_compute_compressedfmt_aligned_width_and_height) {
+                    int bytesPerPixel = 0;
+                    int raster_mode         = 0;   //Adreno unknown raster mode.
+                    int padding_threshold   = 512; //Threshold for padding
+                    //surfaces.
+
+                    LINK_adreno_compute_compressedfmt_aligned_width_and_height(
+                        width, height, format, 0,raster_mode, padding_threshold,
+                        &aligned_w, &aligned_h, &bytesPerPixel);
+                } else {
+                    ALOGW("%s: Warning!! Symbols" \
+                          " compute_compressedfmt_aligned_width_and_height" \
+                          " not found", __FUNCTION__);
+                }
+                break;
+            default: break;
+        }
+    }
+}
+
+void AdrenoMemInfo::getGpuAlignedWidthHeight(int width, int height, int format,
+                            int tile_enabled, int& aligned_w, int& aligned_h)
+{
+    aligned_w = ALIGN(width, 32);
+    aligned_h = ALIGN(height, 32);
+
+    // Don't add any additional padding if debug.gralloc.map_fb_memory
+    // is enabled
+    char property[PROPERTY_VALUE_MAX];
+    if((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
+       (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+       (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+        return;
+    }
+
+    int bpp = 4;
+    switch(format)
+    {
+        case HAL_PIXEL_FORMAT_RGB_888:
+            bpp = 3;
+            break;
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444:
+            bpp = 2;
+            break;
+        default: break;
+    }
+
+    if (libadreno_utils) {
+        int raster_mode         = 0;   // Adreno unknown raster mode.
+        int padding_threshold   = 512; // Threshold for padding surfaces.
+        // the function below computes aligned width and aligned height
+        // based on linear or macro tile mode selected.
+        if(LINK_adreno_compute_aligned_width_and_height) {
+            LINK_adreno_compute_aligned_width_and_height(width,
+                                 height, bpp, tile_enabled,
+                                 raster_mode, padding_threshold,
+                                 &aligned_w, &aligned_h);
+
+        } else if(LINK_adreno_compute_padding) {
+            int surface_tile_height = 1;   // Linear surface
+            aligned_w = LINK_adreno_compute_padding(width, bpp,
+                                 surface_tile_height, raster_mode,
+                                 padding_threshold);
+            ALOGW("%s: Warning!! Old GFX API is used to calculate stride",
+                                                            __FUNCTION__);
+        } else {
+            ALOGW("%s: Warning!! Symbols compute_surface_padding and " \
+                 "compute_aligned_width_and_height not found", __FUNCTION__);
+        }
+   }
+}
+
+int AdrenoMemInfo::isUBWCSupportedByGPU(int format)
+{
+    if (!gfx_ubwc_disable && libadreno_utils) {
+        if (LINK_adreno_isUBWCSupportedByGpu) {
+            ADRENOPIXELFORMAT gpu_format = getGpuPixelFormat(format);
+            return LINK_adreno_isUBWCSupportedByGpu(gpu_format);
+        }
+    }
+    return 0;
+}
+
+ADRENOPIXELFORMAT AdrenoMemInfo::getGpuPixelFormat(int hal_format)
+{
+    switch (hal_format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+            return ADRENO_PIXELFORMAT_R8G8B8A8;
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+            return ADRENO_PIXELFORMAT_R8G8B8X8;
+        case HAL_PIXEL_FORMAT_RGB_565:
+            return ADRENO_PIXELFORMAT_B5G6R5;
+        case HAL_PIXEL_FORMAT_BGR_565:
+            return ADRENO_PIXELFORMAT_R5G6B5;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+            return ADRENO_PIXELFORMAT_NV12;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+            return ADRENO_PIXELFORMAT_NV12_EXT;
+        case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+            return ADRENO_PIXELFORMAT_TP10;
+        case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+        case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+            return ADRENO_PIXELFORMAT_P010;
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
+            return ADRENO_PIXELFORMAT_R10G10B10A2_UNORM;
+        case HAL_PIXEL_FORMAT_RGBX_1010102:
+            return ADRENO_PIXELFORMAT_R10G10B10X2_UNORM;
+        case HAL_PIXEL_FORMAT_ABGR_2101010:
+            return ADRENO_PIXELFORMAT_A2B10G10R10_UNORM;
+        default:
+            ALOGE("%s: No map for format: 0x%x", __FUNCTION__, hal_format);
+            break;
+    }
+    return ADRENO_PIXELFORMAT_UNKNOWN;
+}
+
+//-------------- IAllocController-----------------------//
+IAllocController* IAllocController::sController = NULL;
+IAllocController* IAllocController::getInstance(void)
+{
+    if(sController == NULL) {
+        sController = new IonController();
+    }
+    return sController;
+}
+
+
+//-------------- IonController-----------------------//
+IonController::IonController()
+{
+    allocateIonMem();
+
+    char property[PROPERTY_VALUE_MAX];
+    property_get("video.disable.ubwc", property, "0");
+    mDisableUBWCForEncode = atoi(property);
+}
+
+void IonController::allocateIonMem()
+{
+   mIonAlloc = new IonAlloc();
+}
+
+int IonController::allocate(alloc_data& data, int usage)
+{
+    int ionFlags = 0;
+    int ionHeapId = 0;
+    int ret;
+
+    data.uncached = useUncached(usage);
+    data.allocType = 0;
+
+    if(usage & GRALLOC_USAGE_PROTECTED) {
+        if (usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY) {
+            ionHeapId = ION_HEAP(SD_HEAP_ID);
+            /*
+             * There is currently no flag in ION for Secure Display
+             * VM. Please add it to the define once available.
+             */
+            ionFlags |= ION_SD_FLAGS;
+        } else if (usage & GRALLOC_USAGE_HW_CAMERA_MASK) {
+            ionHeapId = ION_HEAP(SD_HEAP_ID);
+            ionFlags |= (usage & GRALLOC_USAGE_HW_COMPOSER) ? ION_SC_PREVIEW_FLAGS : ION_SC_FLAGS;
+        } else {
+            ionHeapId = ION_HEAP(CP_HEAP_ID);
+            ionFlags |= ION_CP_FLAGS;
+        }
+    } else if(usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
+        //MM Heap is exclusively a secure heap.
+        //If it is used for non secure cases, fallback to IOMMU heap
+        ALOGW("GRALLOC_USAGE_PRIVATE_MM_HEAP \
+                                cannot be used as an insecure heap!\
+                                trying to use system heap instead !!");
+        ionHeapId |= ION_HEAP(ION_SYSTEM_HEAP_ID);
+    }
+
+    if(usage & GRALLOC_USAGE_PRIVATE_CAMERA_HEAP)
+        ionHeapId |= ION_HEAP(ION_CAMERA_HEAP_ID);
+
+    if(usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP)
+        ionHeapId |= ION_HEAP(ION_ADSP_HEAP_ID);
+
+    if(ionFlags & ION_SECURE)
+         data.allocType |= private_handle_t::PRIV_FLAGS_SECURE_BUFFER;
+
+    // if no ion heap flags are set, default to system heap
+    if(!ionHeapId)
+        ionHeapId = ION_HEAP(ION_SYSTEM_HEAP_ID);
+
+    //At this point we should have the right heap set, there is no fallback
+    data.flags = ionFlags;
+    data.heapId = ionHeapId;
+    ret = mIonAlloc->alloc_buffer(data);
+
+    if(ret >= 0 ) {
+        data.allocType |= private_handle_t::PRIV_FLAGS_USES_ION;
+    } else {
+        ALOGE("%s: Failed to allocate buffer - heap: 0x%x flags: 0x%x",
+                __FUNCTION__, ionHeapId, ionFlags);
+    }
+
+    return ret;
+}
+
+IMemAlloc* IonController::getAllocator(int flags)
+{
+    IMemAlloc* memalloc = NULL;
+    if (flags & private_handle_t::PRIV_FLAGS_USES_ION) {
+        memalloc = mIonAlloc;
+    } else {
+        ALOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags);
+    }
+
+    return memalloc;
+}
+
+// helper function
+unsigned int getSize(int format, int width, int height, int usage,
+        const int alignedw, const int alignedh) {
+
+    if (isUBwcEnabled(format, usage)) {
+        return getUBwcSize(width, height, format, alignedw, alignedh);
+    }
+
+    unsigned int size = 0;
+    switch (format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
+        case HAL_PIXEL_FORMAT_ARGB_2101010:
+        case HAL_PIXEL_FORMAT_RGBX_1010102:
+        case HAL_PIXEL_FORMAT_XRGB_2101010:
+        case HAL_PIXEL_FORMAT_BGRA_1010102:
+        case HAL_PIXEL_FORMAT_ABGR_2101010:
+        case HAL_PIXEL_FORMAT_BGRX_1010102:
+        case HAL_PIXEL_FORMAT_XBGR_2101010:
+            size = alignedw * alignedh * 4;
+            break;
+        case HAL_PIXEL_FORMAT_RGB_888:
+            size = alignedw * alignedh * 3;
+            break;
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444:
+        case HAL_PIXEL_FORMAT_RAW16:
+        case HAL_PIXEL_FORMAT_Y16:
+            size = alignedw * alignedh * 2;
+            break;
+        case HAL_PIXEL_FORMAT_RAW12:
+            size = ALIGN(alignedw * alignedh, 4096);
+            break;
+        case HAL_PIXEL_FORMAT_RAW10:
+            size = ALIGN(alignedw * alignedh, 4096);
+            break;
+        case HAL_PIXEL_FORMAT_RAW8:
+        case HAL_PIXEL_FORMAT_Y8:
+            size = alignedw * alignedh;
+            break;
+            // adreno formats
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:  // NV21
+            size  = ALIGN(alignedw*alignedh, 4096);
+            size += ALIGN(2 * ALIGN(width/2, 32) * ALIGN(height/2, 32), 4096);
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:   // NV12
+            // The chroma plane is subsampled,
+            // but the pitch in bytes is unchanged
+            // The GPU needs 4K alignment, but the video decoder needs 8K
+            size  = ALIGN( alignedw * alignedh, 8192);
+            size += ALIGN( alignedw * ALIGN(height/2, 32), 8192);
+            break;
+        case HAL_PIXEL_FORMAT_YV12:
+            if ((format == HAL_PIXEL_FORMAT_YV12) && ((width&1) || (height&1))) {
+                ALOGE("w or h is odd for the YV12 format");
+                return 0;
+            }
+            size = alignedw*alignedh +
+                    (ALIGN(alignedw/2, 16) * (alignedh/2))*2;
+            size = ALIGN(size, (unsigned int)4096);
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            size = ALIGN((alignedw*alignedh) + (alignedw* alignedh)/2 + 1, 4096);
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+            size = ALIGN((alignedw * alignedh * 2) + (alignedw * alignedh) + 1, 4096);
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_422_I:
+        case HAL_PIXEL_FORMAT_YCrCb_422_I:
+        case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+            if(width & 1) {
+                ALOGE("width is odd for the YUV422_SP format");
+                return 0;
+            }
+            size = ALIGN(alignedw * alignedh * 2, 4096);
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+            size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+            size = VENUS_BUFFER_SIZE(COLOR_FMT_NV21, width, height);
+            break;
+        case HAL_PIXEL_FORMAT_BLOB:
+        case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+            if(height != 1) {
+                ALOGE("%s: Buffers with format HAL_PIXEL_FORMAT_BLOB \
+                      must have height==1 ", __FUNCTION__);
+                return 0;
+            }
+            size = width;
+            break;
+        case HAL_PIXEL_FORMAT_NV21_ZSL:
+            size = ALIGN((alignedw*alignedh) + (alignedw* alignedh)/2, 4096);
+            break;
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+            size = alignedw * alignedh * ASTC_BLOCK_SIZE;
+            break;
+        default:
+            ALOGE("%s: Unrecognized pixel format: 0x%x", __FUNCTION__, format);
+            return 0;
+    }
+    return size;
+}
+
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
+        int& alignedw, int &alignedh)
+{
+    unsigned int size;
+
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+            height,
+            format,
+            0,
+            alignedw,
+            alignedh);
+
+    size = getSize(format, width, height, 0 /* usage */, alignedw, alignedh);
+
+    return size;
+}
+
+
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
+        int usage, int& alignedw, int &alignedh)
+{
+    unsigned int size;
+
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+            height,
+            format,
+            usage,
+            alignedw,
+            alignedh);
+
+    size = getSize(format, width, height, usage, alignedw, alignedh);
+
+    return size;
+}
+
+void getYuvUbwcSPPlaneInfo(uint64_t base, int width, int height,
+                           int color_format, struct android_ycbcr* ycbcr)
+{
+    // UBWC buffer has these 4 planes in the following sequence:
+    // Y_Meta_Plane, Y_Plane, UV_Meta_Plane, UV_Plane
+    unsigned int y_meta_stride, y_meta_height, y_meta_size;
+    unsigned int y_stride, y_height, y_size;
+    unsigned int c_meta_stride, c_meta_height, c_meta_size;
+    unsigned int alignment = 4096;
+
+    y_meta_stride = VENUS_Y_META_STRIDE(color_format, width);
+    y_meta_height = VENUS_Y_META_SCANLINES(color_format, height);
+    y_meta_size = ALIGN((y_meta_stride * y_meta_height), alignment);
+
+    y_stride = VENUS_Y_STRIDE(color_format, width);
+    y_height = VENUS_Y_SCANLINES(color_format, height);
+    y_size = ALIGN((y_stride * y_height), alignment);
+
+    c_meta_stride = VENUS_UV_META_STRIDE(color_format, width);
+    c_meta_height = VENUS_UV_META_SCANLINES(color_format, height);
+    c_meta_size = ALIGN((c_meta_stride * c_meta_height), alignment);
+
+    ycbcr->y  = (void*)(base + y_meta_size);
+    ycbcr->cb = (void*)(base + y_meta_size + y_size + c_meta_size);
+    ycbcr->cr = (void*)(base + y_meta_size + y_size +
+                        c_meta_size + 1);
+    ycbcr->ystride = y_stride;
+    ycbcr->cstride = VENUS_UV_STRIDE(color_format, width);
+}
+
+void getYuvSPPlaneInfo(uint64_t base, int width, int height, int bpp,
+                       struct android_ycbcr* ycbcr)
+{
+    unsigned int ystride, cstride;
+
+    ystride = cstride = width * bpp;
+    ycbcr->y  = (void*)base;
+    ycbcr->cb = (void*)(base + ystride * height);
+    ycbcr->cr = (void*)(base + ystride * height + 1);
+    ycbcr->ystride = ystride;
+    ycbcr->cstride = cstride;
+    ycbcr->chroma_step = 2 * bpp;
+}
+
+int getYUVPlaneInfo(private_handle_t* hnd, struct android_ycbcr* ycbcr)
+{
+    int err = 0;
+    int width = hnd->width;
+    int height = hnd->height;
+    int format = hnd->format;
+
+    unsigned int ystride, cstride;
+
+    memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+
+    // Check if UBWC buffer has been rendered in linear format.
+    if (metadata && (metadata->operation & LINEAR_FORMAT)) {
+        format = metadata->linearFormat;
+    }
+
+    // Check metadata if the geometry has been updated.
+    if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+        int usage = 0;
+
+        if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+            usage = GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+        }
+
+        AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(metadata->bufferDim.sliceWidth,
+                   metadata->bufferDim.sliceHeight, format, usage, width, height);
+    }
+
+    // Get the chroma offsets from the handle width/height. We take advantage
+    // of the fact the width _is_ the stride
+    switch (format) {
+        //Semiplanar
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: //Same as YCbCr_420_SP_VENUS
+            getYuvSPPlaneInfo(hnd->base, width, height, 1, ycbcr);
+        break;
+
+        case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+            getYuvSPPlaneInfo(hnd->base, width, height, 2, ycbcr);
+        break;
+
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+            getYuvUbwcSPPlaneInfo(hnd->base, width, height,
+                                  COLOR_FMT_NV12_UBWC, ycbcr);
+            ycbcr->chroma_step = 2;
+        break;
+
+        case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+            getYuvUbwcSPPlaneInfo(hnd->base, width, height,
+                                  COLOR_FMT_NV12_BPP10_UBWC, ycbcr);
+            ycbcr->chroma_step = 3;
+        break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+            getYuvUbwcSPPlaneInfo(hnd->base, width, height,
+                                  COLOR_FMT_P010_UBWC, ycbcr);
+            ycbcr->chroma_step = 4;
+        break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_NV21_ZSL:
+        case HAL_PIXEL_FORMAT_RAW16:
+        case HAL_PIXEL_FORMAT_Y16:
+        case HAL_PIXEL_FORMAT_RAW12:
+        case HAL_PIXEL_FORMAT_RAW10:
+        case HAL_PIXEL_FORMAT_RAW8:
+        case HAL_PIXEL_FORMAT_Y8:
+            getYuvSPPlaneInfo(hnd->base, width, height, 1, ycbcr);
+            std::swap(ycbcr->cb, ycbcr->cr);
+        break;
+
+        //Planar
+        case HAL_PIXEL_FORMAT_YV12:
+            ystride = width;
+            cstride = ALIGN(width/2, 16);
+            ycbcr->y  = (void*)hnd->base;
+            ycbcr->cr = (void*)(hnd->base + ystride * height);
+            ycbcr->cb = (void*)(hnd->base + ystride * height +
+                    cstride * height/2);
+            ycbcr->ystride = ystride;
+            ycbcr->cstride = cstride;
+            ycbcr->chroma_step = 1;
+        break;
+        case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+            ystride = width * 2;
+            cstride = 0;
+            ycbcr->y  = (void*)hnd->base;
+            ycbcr->cr = NULL;
+            ycbcr->cb = NULL;
+            ycbcr->ystride = ystride;
+            ycbcr->cstride = 0;
+            ycbcr->chroma_step = 0;
+        break;
+        //Unsupported formats
+        case HAL_PIXEL_FORMAT_YCbCr_422_I:
+        case HAL_PIXEL_FORMAT_YCrCb_422_I:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+        default:
+        ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__, format);
+        err = -EINVAL;
+    }
+    return err;
+
+}
+
+
+
+// Allocate buffer from width, height and format into a
+// private_handle_t. It is the responsibility of the caller
+// to free the buffer using the free_buffer function
+int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage)
+{
+    alloc_data data;
+    int alignedw, alignedh;
+    gralloc::IAllocController* sAlloc =
+        gralloc::IAllocController::getInstance();
+    data.base = 0;
+    data.fd = -1;
+    data.offset = 0;
+    data.size = getBufferSizeAndDimensions(w, h, format, usage, alignedw,
+                                            alignedh);
+
+    data.align = getpagesize();
+    data.uncached = useUncached(usage);
+    int allocFlags = usage;
+
+    int err = sAlloc->allocate(data, allocFlags);
+    if (0 != err) {
+        ALOGE("%s: allocate failed", __FUNCTION__);
+        return -ENOMEM;
+    }
+
+    if(isUBwcEnabled(format, usage)) {
+      data.allocType |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+    }
+
+    private_handle_t* hnd = new private_handle_t(data.fd, data.size,
+                                                 data.allocType, 0, format,
+                                                 alignedw, alignedh, -1, 0, 0, w, h);
+    hnd->base = (uint64_t) data.base;
+    hnd->offset = data.offset;
+    hnd->gpuaddr = 0;
+    *pHnd = hnd;
+    return 0;
+}
+
+void free_buffer(private_handle_t *hnd)
+{
+    gralloc::IAllocController* sAlloc =
+        gralloc::IAllocController::getInstance();
+    if (hnd && hnd->fd > 0) {
+        IMemAlloc* memalloc = sAlloc->getAllocator(hnd->flags);
+        memalloc->free_buffer((void*)hnd->base, hnd->size, hnd->offset, hnd->fd);
+    }
+    if(hnd)
+        delete hnd;
+
+}
+
+// UBWC helper functions
+static bool isUBwcFormat(int format)
+{
+    // Explicitly defined UBWC formats
+    switch(format)
+    {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+        case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+        case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+            return true;
+        default:
+            return false;
+    }
+}
+
+static bool isUBwcSupported(int format)
+{
+    if (MDPCapabilityInfo::getInstance().isUBwcSupportedByMDP()) {
+        // Existing HAL formats with UBWC support
+        switch(format)
+        {
+            case HAL_PIXEL_FORMAT_BGR_565:
+            case HAL_PIXEL_FORMAT_RGBA_8888:
+            case HAL_PIXEL_FORMAT_RGBX_8888:
+            case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+            case HAL_PIXEL_FORMAT_RGBA_1010102:
+            case HAL_PIXEL_FORMAT_RGBX_1010102:
+                return true;
+            default:
+                break;
+        }
+    }
+    return false;
+}
+
+bool isUBwcEnabled(int format, int usage)
+{
+    // Allow UBWC, if client is using an explicitly defined UBWC pixel format.
+    if (isUBwcFormat(format))
+        return true;
+
+    if ((usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) &&
+        gralloc::IAllocController::getInstance()->isDisableUBWCForEncoder()) {
+            return false;
+    }
+
+    // Allow UBWC, if an OpenGL client sets UBWC usage flag and GPU plus MDP
+    // support the format. OR if a non-OpenGL client like Rotator, sets UBWC
+    // usage flag and MDP supports the format.
+    if ((usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) && isUBwcSupported(format)) {
+        bool enable = true;
+        // Query GPU for UBWC only if buffer is intended to be used by GPU.
+        if (usage & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER)) {
+            enable = AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format);
+        }
+        // Allow UBWC, only if CPU usage flags are not set
+        if (enable && !(usage & (GRALLOC_USAGE_SW_READ_MASK |
+            GRALLOC_USAGE_SW_WRITE_MASK))) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static void getYuvUBwcWidthHeight(int width, int height, int format,
+        int& aligned_w, int& aligned_h)
+{
+    switch (format)
+    {
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+            aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, width);
+            aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, height);
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+            // The macro returns the stride which is 4/3 times the width, hence * 3/4
+            aligned_w = (VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, width) * 3) / 4;
+            aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, height);
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+            // The macro returns the stride which is 2 times the width, hence / 2
+            aligned_w = (VENUS_Y_STRIDE(COLOR_FMT_P010_UBWC, width) / 2);
+            aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_P010_UBWC, height);
+            break;
+        default:
+            ALOGE("%s: Unsupported pixel format: 0x%x", __FUNCTION__, format);
+            aligned_w = 0;
+            aligned_h = 0;
+            break;
+    }
+}
+
+static void getRgbUBwcBlockSize(int bpp, int& block_width, int& block_height)
+{
+    block_width = 0;
+    block_height = 0;
+
+    switch(bpp)
+    {
+         case 2:
+         case 4:
+             block_width = 16;
+             block_height = 4;
+             break;
+         case 8:
+             block_width = 8;
+             block_height = 4;
+             break;
+         case 16:
+             block_width = 4;
+             block_height = 4;
+             break;
+         default:
+             ALOGE("%s: Unsupported bpp: %d", __FUNCTION__, bpp);
+             break;
+    }
+}
+
+static unsigned int getRgbUBwcMetaBufferSize(int width, int height, int bpp)
+{
+    unsigned int size = 0;
+    int meta_width, meta_height;
+    int block_width, block_height;
+
+    getRgbUBwcBlockSize(bpp, block_width, block_height);
+
+    if (!block_width || !block_height) {
+        ALOGE("%s: Unsupported bpp: %d", __FUNCTION__, bpp);
+        return size;
+    }
+
+    // Align meta buffer height to 16 blocks
+    meta_height = ALIGN(((height + block_height - 1) / block_height), 16);
+
+    // Align meta buffer width to 64 blocks
+    meta_width = ALIGN(((width + block_width - 1) / block_width), 64);
+
+    // Align meta buffer size to 4K
+    size = ALIGN((meta_width * meta_height), 4096);
+    return size;
+}
+
+static unsigned int getUBwcSize(int width, int height, int format,
+        const int alignedw, const int alignedh) {
+
+    unsigned int size = 0;
+    switch (format) {
+        case HAL_PIXEL_FORMAT_BGR_565:
+            size = alignedw * alignedh * 2;
+            size += getRgbUBwcMetaBufferSize(width, height, 2);
+            break;
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
+        case HAL_PIXEL_FORMAT_RGBX_1010102:
+            size = alignedw * alignedh * 4;
+            size += getRgbUBwcMetaBufferSize(width, height, 4);
+            break;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+            size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, width, height);
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+            size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_BPP10_UBWC, width, height);
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+            size = VENUS_BUFFER_SIZE(COLOR_FMT_P010_UBWC, width, height);
+            break;
+        default:
+            ALOGE("%s: Unsupported pixel format: 0x%x", __FUNCTION__, format);
+            break;
+    }
+    return size;
+}
+
+int getRgbDataAddress(private_handle_t* hnd, void** rgb_data)
+{
+    int err = 0;
+
+    // This api is for RGB* formats
+    if (!isUncompressedRgbFormat(hnd->format)) {
+        return -EINVAL;
+    }
+
+    // linear buffer
+    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED)) {
+        *rgb_data = (void*)hnd->base;
+        return err;
+    }
+
+    // Ubwc buffers
+    unsigned int meta_size = 0;
+    switch (hnd->format) {
+        case HAL_PIXEL_FORMAT_BGR_565:
+            meta_size = getRgbUBwcMetaBufferSize(hnd->width, hnd->height, 2);
+            break;
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
+        case HAL_PIXEL_FORMAT_RGBX_1010102:
+            meta_size = getRgbUBwcMetaBufferSize(hnd->width, hnd->height, 4);
+            break;
+        default:
+            ALOGE("%s:Unsupported RGB format: 0x%x", __FUNCTION__, hnd->format);
+            err = -EINVAL;
+            break;
+    }
+
+    *rgb_data = (void*)(hnd->base + meta_size);
+    return err;
+}
+
+int getBufferLayout(private_handle_t *hnd, uint32_t stride[4],
+        uint32_t offset[4], uint32_t *num_planes) {
+    if (!hnd || !stride || !offset || !num_planes) {
+        return -EINVAL;
+    }
+
+    struct android_ycbcr yuvInfo = {};
+    *num_planes = 1;
+    stride[0] = 0;
+
+    switch (hnd->format) {
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444:
+            stride[0] = hnd->width * 2;
+            break;
+        case HAL_PIXEL_FORMAT_RGB_888:
+            stride[0] = hnd->width * 3;
+            break;
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_BGRX_8888:
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
+        case HAL_PIXEL_FORMAT_ARGB_2101010:
+        case HAL_PIXEL_FORMAT_RGBX_1010102:
+        case HAL_PIXEL_FORMAT_XRGB_2101010:
+        case HAL_PIXEL_FORMAT_BGRA_1010102:
+        case HAL_PIXEL_FORMAT_ABGR_2101010:
+        case HAL_PIXEL_FORMAT_BGRX_1010102:
+        case HAL_PIXEL_FORMAT_XBGR_2101010:
+            stride[0] = hnd->width * 4;
+            break;
+    }
+
+    // Format is RGB
+    if (stride[0]) {
+        return 0;
+    }
+
+    (*num_planes)++;
+    int ret = getYUVPlaneInfo(hnd, &yuvInfo);
+    if (ret < 0) {
+        ALOGE("%s failed", __FUNCTION__);
+        return ret;
+    }
+
+    stride[0] = static_cast<uint32_t>(yuvInfo.ystride);
+    offset[0] = static_cast<uint32_t>(
+                    reinterpret_cast<uint64_t>(yuvInfo.y) - hnd->base);
+    stride[1] = static_cast<uint32_t>(yuvInfo.cstride);
+    switch (hnd->format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+        case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+        case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+        case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+            offset[1] = static_cast<uint32_t>(
+                    reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base);
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+            offset[1] = static_cast<uint32_t>(
+                    reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base);
+            break;
+        case HAL_PIXEL_FORMAT_YV12:
+            offset[1] = static_cast<uint32_t>(
+                    reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base);
+            stride[2] = static_cast<uint32_t>(yuvInfo.cstride);
+            offset[2] = static_cast<uint32_t>(
+                    reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base);
+            (*num_planes)++;
+            break;
+        default:
+            ALOGW("%s: Unsupported format %s", __FUNCTION__,
+                    qdutils::GetHALPixelFormatString(hnd->format));
+            ret = -EINVAL;
+    }
+
+    if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+        std::fill(offset, offset + 4, 0);
+    }
+
+    return 0;
+}
diff --git a/sdm845/libgralloc/alloc_controller.h b/sdm845/libgralloc/alloc_controller.h
new file mode 100644
index 0000000..45977e2
--- /dev/null
+++ b/sdm845/libgralloc/alloc_controller.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2011-2012, 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 GRALLOC_ALLOCCONTROLLER_H
+#define GRALLOC_ALLOCCONTROLLER_H
+
+#define SZ_2M 0x200000
+#define SZ_1M 0x100000
+#define SZ_4K 0x1000
+
+/* TODO: Move this to the common makefile */
+#ifdef MASTER_SIDE_CP
+#define SECURE_ALIGN SZ_4K
+#else
+#define SECURE_ALIGN SZ_1M
+#endif
+
+namespace gralloc {
+
+struct alloc_data;
+class IMemAlloc;
+class IonAlloc;
+
+class IAllocController {
+
+    public:
+    /* Allocate using a suitable method
+     * Returns the type of buffer allocated
+     */
+    virtual int allocate(alloc_data& data, int usage) = 0;
+
+    virtual IMemAlloc* getAllocator(int flags) = 0;
+
+    virtual bool isDisableUBWCForEncoder() = 0;
+
+    virtual ~IAllocController() {};
+
+    static IAllocController* getInstance(void);
+
+    private:
+    static IAllocController* sController;
+
+};
+
+class IonController : public IAllocController {
+
+    public:
+    virtual int allocate(alloc_data& data, int usage);
+
+    virtual IMemAlloc* getAllocator(int flags);
+
+    virtual bool isDisableUBWCForEncoder() {
+        return mDisableUBWCForEncode;
+    }
+
+    IonController();
+
+    private:
+    IonAlloc* mIonAlloc;
+    bool mDisableUBWCForEncode;
+    void allocateIonMem();
+
+};
+} //end namespace gralloc
+#endif // GRALLOC_ALLOCCONTROLLER_H
diff --git a/sdm845/libgralloc/fb_priv.h b/sdm845/libgralloc/fb_priv.h
new file mode 100644
index 0000000..e2eba6a
--- /dev/null
+++ b/sdm845/libgralloc/fb_priv.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FB_PRIV_H
+#define FB_PRIV_H
+#include <linux/fb.h>
+#include <linux/msm_mdp.h>
+
+#define NUM_FRAMEBUFFERS_MIN  2
+#define NUM_FRAMEBUFFERS_MAX  3
+
+#define NO_SURFACEFLINGER_SWAPINTERVAL
+#define COLOR_FORMAT(x) (x & 0xFFF) // Max range for colorFormats is 0 - FFF
+
+struct private_handle_t;
+
+enum {
+    // flag to indicate we'll post this buffer
+    PRIV_USAGE_LOCKED_FOR_POST = 0x80000000,
+    PRIV_MIN_SWAP_INTERVAL = 0,
+    PRIV_MAX_SWAP_INTERVAL = 1,
+};
+
+struct private_module_t {
+    gralloc_module_t base;
+    struct private_handle_t* framebuffer;
+    uint32_t fbFormat;
+    uint32_t flags;
+    uint32_t numBuffers;
+    uint32_t bufferMask;
+    pthread_mutex_t lock;
+    struct fb_var_screeninfo info;
+    struct fb_fix_screeninfo finfo;
+    float xdpi;
+    float ydpi;
+    float fps;
+    uint32_t swapInterval;
+};
+
+
+
+#endif /* FB_PRIV_H */
diff --git a/sdm845/libgralloc/framebuffer.cpp b/sdm845/libgralloc/framebuffer.cpp
new file mode 100644
index 0000000..dd4842f
--- /dev/null
+++ b/sdm845/libgralloc/framebuffer.cpp
@@ -0,0 +1,457 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-2014 The Linux Foundation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/mman.h>
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <dlfcn.h>
+
+#include <hardware/hardware.h>
+
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <cutils/atomic.h>
+
+#include <linux/fb.h>
+#include <linux/msm_mdp.h>
+
+#ifndef TARGET_HEADLESS
+#include <GLES/gl.h>
+#endif
+
+#include "gralloc_priv.h"
+#include "fb_priv.h"
+#include "gr.h"
+#include <cutils/properties.h>
+#include <profiler.h>
+
+#define EVEN_OUT(x) if (x & 0x0001) {x--;}
+
+enum {
+    PAGE_FLIP = 0x00000001,
+};
+
+struct fb_context_t {
+    framebuffer_device_t  device;
+    //fd - which is returned on open
+    int fbFd;
+};
+
+static int fb_setSwapInterval(struct framebuffer_device_t* dev,
+                              int interval)
+{
+    //XXX: Get the value here and implement along with
+    //single vsync in HWC
+    char pval[PROPERTY_VALUE_MAX];
+    property_get("debug.egl.swapinterval", pval, "-1");
+    int property_interval = atoi(pval);
+    if (property_interval >= 0)
+        interval = property_interval;
+
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+        dev->common.module);
+    if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval)
+        return -EINVAL;
+
+    m->swapInterval = interval;
+    return 0;
+}
+
+static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
+{
+    private_module_t* m =
+        reinterpret_cast<private_module_t*>(dev->common.module);
+    private_handle_t *hnd = static_cast<private_handle_t*>
+        (const_cast<native_handle_t*>(buffer));
+    fb_context_t *ctx = reinterpret_cast<fb_context_t*>(dev);
+    const unsigned int offset = (unsigned int) (hnd->base -
+            m->framebuffer->base);
+    m->info.activate = FB_ACTIVATE_VBL;
+    m->info.yoffset = (int)(offset / m->finfo.line_length);
+    if (ioctl(ctx->fbFd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
+        ALOGE("%s: FBIOPUT_VSCREENINFO for primary failed, str: %s",
+                __FUNCTION__, strerror(errno));
+        return -errno;
+    }
+    return 0;
+}
+
+static int fb_compositionComplete(struct framebuffer_device_t* dev)
+{
+    // TODO: Properly implement composition complete callback
+    if(!dev) {
+        return -1;
+    }
+#ifndef TARGET_HEADLESS
+    glFinish();
+#endif
+
+    return 0;
+}
+
+int mapFrameBufferLocked(framebuffer_device_t *dev)
+{
+    private_module_t* module =
+        reinterpret_cast<private_module_t*>(dev->common.module);
+    fb_context_t *ctx = reinterpret_cast<fb_context_t*>(dev);
+    // already initialized...
+    if (module->framebuffer) {
+        return 0;
+    }
+    char const * const device_template[] = {
+        "/dev/graphics/fb%u",
+        "/dev/fb%u",
+        0 };
+
+    int fd = -1;
+    int i=0;
+    char name[64];
+    char property[PROPERTY_VALUE_MAX];
+
+    while ((fd==-1) && device_template[i]) {
+        snprintf(name, 64, device_template[i], 0);
+        fd = open(name, O_RDWR, 0);
+        i++;
+    }
+    if (fd < 0)
+        return -errno;
+
+    struct fb_fix_screeninfo finfo;
+    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
+        close(fd);
+        return -errno;
+    }
+
+    struct fb_var_screeninfo info;
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) {
+        close(fd);
+        return -errno;
+    }
+
+    info.reserved[0] = 0;
+    info.reserved[1] = 0;
+    info.reserved[2] = 0;
+    info.xoffset = 0;
+    info.yoffset = 0;
+    info.activate = FB_ACTIVATE_NOW;
+
+    /* Interpretation of offset for color fields: All offsets are from the
+     * right, inside a "pixel" value, which is exactly 'bits_per_pixel' wide
+     * (means: you can use the offset as right argument to <<). A pixel
+     * afterwards is a bit stream and is written to video memory as that
+     * unmodified. This implies big-endian byte order if bits_per_pixel is
+     * greater than 8.
+     */
+
+    if(info.bits_per_pixel == 32) {
+        /*
+         * Explicitly request RGBA_8888
+         */
+        info.bits_per_pixel = 32;
+        info.red.offset     = 24;
+        info.red.length     = 8;
+        info.green.offset   = 16;
+        info.green.length   = 8;
+        info.blue.offset    = 8;
+        info.blue.length    = 8;
+        info.transp.offset  = 0;
+        info.transp.length  = 8;
+
+        /* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we
+         * do not use the MDP for composition (i.e. hw composition == 0), ask
+         * for RGBA instead of RGBX. */
+        if (property_get("debug.sf.hw", property, NULL) > 0 &&
+                                                           atoi(property) == 0)
+            module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
+        else if(property_get("debug.composition.type", property, NULL) > 0 &&
+                (strncmp(property, "mdp", 3) == 0))
+            module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
+        else
+            module->fbFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+    } else {
+        /*
+         * Explicitly request 5/6/5
+         */
+        info.bits_per_pixel = 16;
+        info.red.offset     = 11;
+        info.red.length     = 5;
+        info.green.offset   = 5;
+        info.green.length   = 6;
+        info.blue.offset    = 0;
+        info.blue.length    = 5;
+        info.transp.offset  = 0;
+        info.transp.length  = 0;
+        module->fbFormat = HAL_PIXEL_FORMAT_RGB_565;
+    }
+
+    //adreno needs 4k aligned offsets. Max hole size is 4096-1
+    unsigned int size = roundUpToPageSize(info.yres * info.xres *
+                                               (info.bits_per_pixel/8));
+
+    /*
+     * Request NUM_BUFFERS screens (at least 2 for page flipping)
+     */
+    int numberOfBuffers = (int)(finfo.smem_len/size);
+    ALOGV("num supported framebuffers in kernel = %d", numberOfBuffers);
+
+    if (property_get("debug.gr.numframebuffers", property, NULL) > 0) {
+        int num = atoi(property);
+        if ((num >= NUM_FRAMEBUFFERS_MIN) && (num <= NUM_FRAMEBUFFERS_MAX)) {
+            numberOfBuffers = num;
+        }
+    }
+    if (numberOfBuffers > NUM_FRAMEBUFFERS_MAX)
+        numberOfBuffers = NUM_FRAMEBUFFERS_MAX;
+
+    ALOGV("We support %d buffers", numberOfBuffers);
+
+    //consider the included hole by 4k alignment
+    uint32_t line_length = (info.xres * info.bits_per_pixel / 8);
+    info.yres_virtual = (uint32_t) ((size * numberOfBuffers) / line_length);
+
+    uint32_t flags = PAGE_FLIP;
+
+    if (info.yres_virtual < ((size * 2) / line_length) ) {
+        // we need at least 2 for page-flipping
+        info.yres_virtual = (int)(size / line_length);
+        flags &= ~PAGE_FLIP;
+        ALOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
+              info.yres_virtual, info.yres*2);
+    }
+
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) {
+        close(fd);
+        return -errno;
+    }
+
+    if (int(info.width) <= 0 || int(info.height) <= 0) {
+        // the driver doesn't return that information
+        // default to 160 dpi
+        info.width  = (uint32_t)(((float)(info.xres) * 25.4f)/160.0f + 0.5f);
+        info.height = (uint32_t)(((float)(info.yres) * 25.4f)/160.0f + 0.5f);
+    }
+
+    float xdpi = ((float)(info.xres) * 25.4f) / (float)info.width;
+    float ydpi = ((float)(info.yres) * 25.4f) / (float)info.height;
+
+#ifdef MSMFB_METADATA_GET
+    struct msmfb_metadata metadata;
+    memset(&metadata, 0 , sizeof(metadata));
+    metadata.op = metadata_op_frame_rate;
+    if (ioctl(fd, MSMFB_METADATA_GET, &metadata) == -1) {
+        ALOGE("Error retrieving panel frame rate");
+        close(fd);
+        return -errno;
+    }
+    float fps = (float)metadata.data.panel_frame_rate;
+#else
+    //XXX: Remove reserved field usage on all baselines
+    //The reserved[3] field is used to store FPS by the driver.
+    float fps  = info.reserved[3] & 0xFF;
+#endif
+    ALOGI("using (fd=%d)\n"
+          "id           = %s\n"
+          "xres         = %d px\n"
+          "yres         = %d px\n"
+          "xres_virtual = %d px\n"
+          "yres_virtual = %d px\n"
+          "bpp          = %d\n"
+          "r            = %2u:%u\n"
+          "g            = %2u:%u\n"
+          "b            = %2u:%u\n",
+          fd,
+          finfo.id,
+          info.xres,
+          info.yres,
+          info.xres_virtual,
+          info.yres_virtual,
+          info.bits_per_pixel,
+          info.red.offset, info.red.length,
+          info.green.offset, info.green.length,
+          info.blue.offset, info.blue.length
+         );
+
+    ALOGI("width        = %d mm (%f dpi)\n"
+          "height       = %d mm (%f dpi)\n"
+          "refresh rate = %.2f Hz\n",
+          info.width,  xdpi,
+          info.height, ydpi,
+          fps
+         );
+
+
+    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
+        close(fd);
+        return -errno;
+    }
+
+    if (finfo.smem_len <= 0) {
+        close(fd);
+        return -errno;
+    }
+
+    module->flags = flags;
+    module->info = info;
+    module->finfo = finfo;
+    module->xdpi = xdpi;
+    module->ydpi = ydpi;
+    module->fps = fps;
+    module->swapInterval = 1;
+
+    CALC_INIT();
+
+    /*
+     * map the framebuffer
+     */
+
+    module->numBuffers = info.yres_virtual / info.yres;
+    module->bufferMask = 0;
+    //adreno needs page aligned offsets. Align the fbsize to pagesize.
+    unsigned int fbSize = roundUpToPageSize(finfo.line_length * info.yres)*
+                    module->numBuffers;
+    void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+    if (vaddr == MAP_FAILED) {
+        ALOGE("Error mapping the framebuffer (%s)", strerror(errno));
+        close(fd);
+        return -errno;
+    }
+    //store the framebuffer fd in the ctx
+    ctx->fbFd = fd;
+#ifdef MSMFB_METADATA_GET
+    memset(&metadata, 0 , sizeof(metadata));
+    metadata.op = metadata_op_get_ion_fd;
+    // get the ION fd for the framebuffer, as GPU needs ION fd
+    if (ioctl(fd, MSMFB_METADATA_GET, &metadata) == -1) {
+        ALOGE("Error getting ION fd (%s)", strerror(errno));
+        close(fd);
+        return -errno;
+    }
+    if(metadata.data.fbmem_ionfd < 0) {
+        ALOGE("Error: Ioctl returned invalid ION fd = %d",
+                                        metadata.data.fbmem_ionfd);
+        close(fd);
+        return -errno;
+    }
+    fd = metadata.data.fbmem_ionfd;
+#endif
+    // Create framebuffer handle using the ION fd
+    module->framebuffer = new private_handle_t(fd, fbSize,
+                                        private_handle_t::PRIV_FLAGS_USES_ION,
+                                        BUFFER_TYPE_UI,
+                                        module->fbFormat, info.xres, info.yres);
+    module->framebuffer->base = uint64_t(vaddr);
+    memset(vaddr, 0, fbSize);
+    //Enable vsync
+    int enable = 1;
+    ioctl(ctx->fbFd, MSMFB_OVERLAY_VSYNC_CTRL, &enable);
+    return 0;
+}
+
+static int mapFrameBuffer(framebuffer_device_t *dev)
+{
+    int err = -1;
+    char property[PROPERTY_VALUE_MAX];
+    if((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
+       (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+        (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+        private_module_t* module =
+            reinterpret_cast<private_module_t*>(dev->common.module);
+        pthread_mutex_lock(&module->lock);
+        err = mapFrameBufferLocked(dev);
+        pthread_mutex_unlock(&module->lock);
+    }
+    return err;
+}
+
+/*****************************************************************************/
+
+static int fb_close(struct hw_device_t *dev)
+{
+    fb_context_t* ctx = (fb_context_t*)dev;
+    if (ctx) {
+#ifdef MSMFB_METADATA_GET
+        if(ctx->fbFd >=0) {
+            close(ctx->fbFd);
+        }
+#endif
+        //Hack until fbdev is removed. Framework could close this causing hwc a
+        //pain.
+        //free(ctx);
+    }
+    return 0;
+}
+
+int fb_device_open(hw_module_t const* module, const char* name,
+                   hw_device_t** device)
+{
+    int status = -EINVAL;
+    if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
+        alloc_device_t* gralloc_device;
+        status = gralloc_open(module, &gralloc_device);
+        if (status < 0)
+            return status;
+
+        /* initialize our state here */
+        fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
+        if(dev == NULL) {
+            gralloc_close(gralloc_device);
+            return status;
+        }
+        memset(dev, 0, sizeof(*dev));
+
+        /* initialize the procs */
+        dev->device.common.tag      = HARDWARE_DEVICE_TAG;
+        dev->device.common.version  = 0;
+        dev->device.common.module   = const_cast<hw_module_t*>(module);
+        dev->device.common.close    = fb_close;
+        dev->device.setSwapInterval = fb_setSwapInterval;
+        dev->device.post            = fb_post;
+        dev->device.setUpdateRect   = 0;
+        dev->device.compositionComplete = fb_compositionComplete;
+
+        status = mapFrameBuffer((framebuffer_device_t*)dev);
+        private_module_t* m = (private_module_t*)dev->device.common.module;
+        if (status >= 0) {
+            int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
+            const_cast<uint32_t&>(dev->device.flags) = 0;
+            const_cast<uint32_t&>(dev->device.width) = m->info.xres;
+            const_cast<uint32_t&>(dev->device.height) = m->info.yres;
+            const_cast<int&>(dev->device.stride) = stride;
+            const_cast<int&>(dev->device.format) = m->fbFormat;
+            const_cast<float&>(dev->device.xdpi) = m->xdpi;
+            const_cast<float&>(dev->device.ydpi) = m->ydpi;
+            const_cast<float&>(dev->device.fps) = m->fps;
+            const_cast<int&>(dev->device.minSwapInterval) =
+                                                        PRIV_MIN_SWAP_INTERVAL;
+            const_cast<int&>(dev->device.maxSwapInterval) =
+                                                        PRIV_MAX_SWAP_INTERVAL;
+            const_cast<int&>(dev->device.numFramebuffers) = m->numBuffers;
+            dev->device.setUpdateRect = 0;
+
+            *device = &dev->device.common;
+        }
+
+        // Close the gralloc module
+        gralloc_close(gralloc_device);
+    }
+    return status;
+}
diff --git a/sdm845/libgralloc/gpu.cpp b/sdm845/libgralloc/gpu.cpp
new file mode 100644
index 0000000..c57ff90
--- /dev/null
+++ b/sdm845/libgralloc/gpu.cpp
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (c) 2011-2014,2017 The Linux Foundation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <cutils/properties.h>
+#include <sys/mman.h>
+#include <linux/msm_ion.h>
+#include <qdMetaData.h>
+#include <algorithm>
+
+#include "gr.h"
+#include "gpu.h"
+#include "memalloc.h"
+#include "alloc_controller.h"
+
+using namespace gralloc;
+
+gpu_context_t::gpu_context_t(const private_module_t* module,
+                             IAllocController* alloc_ctrl ) :
+    mAllocCtrl(alloc_ctrl)
+{
+    // Zero out the alloc_device_t
+    memset(static_cast<alloc_device_t*>(this), 0, sizeof(alloc_device_t));
+
+    // Initialize the procs
+    common.tag     = HARDWARE_DEVICE_TAG;
+    common.version = 0;
+    common.module  = const_cast<hw_module_t*>(&module->base.common);
+    common.close   = gralloc_close;
+    alloc          = gralloc_alloc;
+    free           = gralloc_free;
+
+}
+
+int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage,
+                                        buffer_handle_t* pHandle, int bufferType,
+                                        int format, int width, int height)
+{
+    int err = 0;
+    int flags = 0;
+    int alignedw = 0;
+    int alignedh = 0;
+
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+            height,
+            format,
+            usage,
+            alignedw,
+            alignedh);
+
+    size = roundUpToPageSize(size);
+    alloc_data data;
+    data.offset = 0;
+    data.fd = -1;
+    data.base = 0;
+    if(format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED)
+        data.align = 8192;
+    else
+        data.align = getpagesize();
+
+    if (usage & GRALLOC_USAGE_PROTECTED) {
+            if ((usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY) ||
+                (usage & GRALLOC_USAGE_HW_CAMERA_MASK)) {
+                /* The alignment here reflects qsee mmu V7L/V8L requirement */
+                data.align = SZ_2M;
+            } else {
+                data.align = SECURE_ALIGN;
+            }
+        size = ALIGN(size, data.align);
+    }
+
+    data.size = size;
+    data.pHandle = (uintptr_t) pHandle;
+    err = mAllocCtrl->allocate(data, usage);
+
+    if (!err) {
+        /* allocate memory for enhancement data */
+        alloc_data eData;
+        eData.fd = -1;
+        eData.base = 0;
+        eData.offset = 0;
+        eData.size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+        eData.pHandle = data.pHandle;
+        eData.align = getpagesize();
+        int eDataUsage = 0;
+        int eDataErr = mAllocCtrl->allocate(eData, eDataUsage);
+        ALOGE_IF(eDataErr, "gralloc failed for eDataErr=%s",
+                                          strerror(-eDataErr));
+
+        if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY) {
+            flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
+        }
+
+        if (usage & GRALLOC_USAGE_PRIVATE_INTERNAL_ONLY) {
+            flags |= private_handle_t::PRIV_FLAGS_INTERNAL_ONLY;
+        }
+
+        if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER ) {
+            flags |= private_handle_t::PRIV_FLAGS_VIDEO_ENCODER;
+        }
+
+        if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
+            flags |= private_handle_t::PRIV_FLAGS_CAMERA_WRITE;
+        }
+
+        if (usage & GRALLOC_USAGE_HW_CAMERA_READ) {
+            flags |= private_handle_t::PRIV_FLAGS_CAMERA_READ;
+        }
+
+        if (usage & GRALLOC_USAGE_HW_COMPOSER) {
+            flags |= private_handle_t::PRIV_FLAGS_HW_COMPOSER;
+        }
+
+        if (usage & GRALLOC_USAGE_HW_TEXTURE) {
+            flags |= private_handle_t::PRIV_FLAGS_HW_TEXTURE;
+        }
+
+        if(usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY) {
+            flags |= private_handle_t::PRIV_FLAGS_SECURE_DISPLAY;
+        }
+
+        if (isUBwcEnabled(format, usage)) {
+            flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+        }
+
+        if(usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
+            flags |= private_handle_t::PRIV_FLAGS_CPU_RENDERED;
+        }
+
+        if (usage & (GRALLOC_USAGE_HW_VIDEO_ENCODER |
+                GRALLOC_USAGE_HW_CAMERA_WRITE |
+                GRALLOC_USAGE_HW_RENDER |
+                GRALLOC_USAGE_HW_FB)) {
+            flags |= private_handle_t::PRIV_FLAGS_NON_CPU_WRITER;
+        }
+
+        if(usage & GRALLOC_USAGE_HW_COMPOSER) {
+            flags |= private_handle_t::PRIV_FLAGS_DISP_CONSUMER;
+        }
+
+        if(false == data.uncached) {
+            flags |= private_handle_t::PRIV_FLAGS_CACHED;
+        }
+
+        flags |= data.allocType;
+        uint64_t eBaseAddr = (uint64_t)(eData.base) + eData.offset;
+        private_handle_t *hnd = new private_handle_t(data.fd, size, flags,
+                bufferType, format, alignedw, alignedh,
+                eData.fd, eData.offset, eBaseAddr, width, height);
+
+        hnd->offset = data.offset;
+        hnd->base = (uint64_t)(data.base) + data.offset;
+        hnd->gpuaddr = 0;
+        ColorSpace_t colorSpace = ITU_R_601;
+        setMetaData(hnd, UPDATE_COLOR_SPACE, (void*) &colorSpace);
+        *pHandle = hnd;
+    }
+
+    ALOGE_IF(err, "gralloc failed err=%s", strerror(-err));
+    return err;
+}
+
+void gpu_context_t::getGrallocInformationFromFormat(int inputFormat,
+                                                    int *bufferType)
+{
+    *bufferType = BUFFER_TYPE_VIDEO;
+
+    if (isUncompressedRgbFormat(inputFormat) == TRUE) {
+        // RGB formats
+        *bufferType = BUFFER_TYPE_UI;
+    }
+}
+
+int gpu_context_t::gralloc_alloc_framebuffer_locked(int usage,
+                                                    buffer_handle_t* pHandle)
+{
+    private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
+
+    // This allocation will only happen when gralloc is in fb mode
+
+    if (m->framebuffer == NULL) {
+        ALOGE("%s: Invalid framebuffer", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    const unsigned int bufferMask = m->bufferMask;
+    const uint32_t numBuffers = m->numBuffers;
+    unsigned int bufferSize = m->finfo.line_length * m->info.yres;
+
+    //adreno needs FB size to be page aligned
+    bufferSize = roundUpToPageSize(bufferSize);
+
+    if (numBuffers == 1) {
+        // If we have only one buffer, we never use page-flipping. Instead,
+        // we return a regular buffer which will be memcpy'ed to the main
+        // screen when post is called.
+        int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
+        return gralloc_alloc_buffer(bufferSize, newUsage, pHandle, BUFFER_TYPE_UI,
+                                    m->fbFormat, m->info.xres, m->info.yres);
+    }
+
+    if (bufferMask >= ((1LU<<numBuffers)-1)) {
+        // We ran out of buffers.
+        return -ENOMEM;
+    }
+
+    // create a "fake" handle for it
+    uint64_t vaddr = uint64_t(m->framebuffer->base);
+    // As GPU needs ION FD, the private handle is created
+    // using ION fd and ION flags are set
+    private_handle_t* hnd = new private_handle_t(
+        dup(m->framebuffer->fd), bufferSize,
+        private_handle_t::PRIV_FLAGS_USES_ION |
+        private_handle_t::PRIV_FLAGS_FRAMEBUFFER,
+        BUFFER_TYPE_UI, m->fbFormat, m->info.xres,
+        m->info.yres);
+
+    // find a free slot
+    for (uint32_t i=0 ; i<numBuffers ; i++) {
+        if ((bufferMask & (1LU<<i)) == 0) {
+            m->bufferMask |= (uint32_t)(1LU<<i);
+            break;
+        }
+        vaddr += bufferSize;
+    }
+    hnd->base = vaddr;
+    hnd->offset = (unsigned int)(vaddr - m->framebuffer->base);
+    *pHandle = hnd;
+    return 0;
+}
+
+
+int gpu_context_t::gralloc_alloc_framebuffer(int usage,
+                                             buffer_handle_t* pHandle)
+{
+    private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
+    pthread_mutex_lock(&m->lock);
+    int err = gralloc_alloc_framebuffer_locked(usage, pHandle);
+    pthread_mutex_unlock(&m->lock);
+    return err;
+}
+
+int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
+                              buffer_handle_t* pHandle, int* pStride,
+                              unsigned int bufferSize) {
+    if (!pHandle || !pStride)
+        return -EINVAL;
+
+    unsigned int size;
+    int alignedw, alignedh;
+    int grallocFormat = format;
+    int bufferType;
+
+    //If input format is HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED then based on
+    //the usage bits, gralloc assigns a format.
+    if(format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
+       format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+        if (usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC)
+            grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+        else if(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
+            if(MDPCapabilityInfo::getInstance().isWBUBWCSupportedByMDP() &&
+               !IAllocController::getInstance()->isDisableUBWCForEncoder() &&
+               usage & GRALLOC_USAGE_HW_COMPOSER)
+              grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+            else
+              grallocFormat = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; //NV12
+        } else if((usage & GRALLOC_USAGE_HW_CAMERA_MASK)
+                == GRALLOC_USAGE_HW_CAMERA_ZSL)
+            grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL; //NV21 ZSL
+        else if(usage & GRALLOC_USAGE_HW_CAMERA_READ)
+            grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
+        else if(usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
+           if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+               grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL; //NV21
+           } else {
+               grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS; //NV12 preview
+           }
+        } else if(usage & GRALLOC_USAGE_HW_COMPOSER)
+            //XXX: If we still haven't set a format, default to RGBA8888
+            grallocFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+        else if(format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+            //If no other usage flags are detected, default the
+            //flexible YUV format to NV21_ZSL
+            grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL;
+        }
+    }
+
+    bool useFbMem = false;
+    char property[PROPERTY_VALUE_MAX];
+    char isUBWC[PROPERTY_VALUE_MAX];
+    if (usage & GRALLOC_USAGE_HW_FB) {
+        if ((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
+            (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+            (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+            useFbMem = true;
+        } else {
+            usage &= ~GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+            if (property_get("debug.gralloc.enable_fb_ubwc", isUBWC, NULL) > 0){
+                if ((!strncmp(isUBWC, "1", PROPERTY_VALUE_MAX)) ||
+                    (!strncasecmp(isUBWC, "true", PROPERTY_VALUE_MAX))) {
+                    // Allocate UBWC aligned framebuffer
+                    usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+                }
+            }
+        }
+    }
+
+    getGrallocInformationFromFormat(grallocFormat, &bufferType);
+    size = getBufferSizeAndDimensions(w, h, grallocFormat, usage, alignedw,
+                   alignedh);
+
+    if ((unsigned int)size <= 0)
+        return -EINVAL;
+    size = (bufferSize >= size)? bufferSize : size;
+
+    int err = 0;
+    if(useFbMem) {
+        err = gralloc_alloc_framebuffer(usage, pHandle);
+    } else {
+        err = gralloc_alloc_buffer(size, usage, pHandle, bufferType,
+                                   grallocFormat, w, h);
+    }
+
+    if (err < 0) {
+        return err;
+    }
+
+    *pStride = alignedw;
+    return 0;
+}
+
+int gpu_context_t::free_impl(private_handle_t const* hnd) {
+    private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
+    if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
+        const unsigned int bufferSize = m->finfo.line_length * m->info.yres;
+        unsigned int index = (unsigned int) ((hnd->base - m->framebuffer->base)
+                / bufferSize);
+        m->bufferMask &= (uint32_t)~(1LU<<index);
+    } else {
+
+        terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
+        IMemAlloc* memalloc = mAllocCtrl->getAllocator(hnd->flags);
+        int err = memalloc->free_buffer((void*)hnd->base, hnd->size,
+                                        hnd->offset, hnd->fd);
+        if(err)
+            return err;
+        // free the metadata space
+        unsigned int size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+        err = memalloc->free_buffer((void*)hnd->base_metadata,
+                                    size, hnd->offset_metadata,
+                                    hnd->fd_metadata);
+        if (err)
+            return err;
+    }
+
+    delete hnd;
+    return 0;
+}
+
+int gpu_context_t::gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
+                                 int usage, buffer_handle_t* pHandle,
+                                 int* pStride)
+{
+    if (!dev) {
+        return -EINVAL;
+    }
+    gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
+    return gpu->alloc_impl(w, h, format, usage, pHandle, pStride, 0);
+}
+int gpu_context_t::gralloc_alloc_size(alloc_device_t* dev, int w, int h,
+                                      int format, int usage,
+                                      buffer_handle_t* pHandle, int* pStride,
+                                      int bufferSize)
+{
+    if (!dev) {
+        return -EINVAL;
+    }
+    gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
+    return gpu->alloc_impl(w, h, format, usage, pHandle, pStride, bufferSize);
+}
+
+
+int gpu_context_t::gralloc_free(alloc_device_t* dev,
+                                buffer_handle_t handle)
+{
+    if (private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
+    gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
+    return gpu->free_impl(hnd);
+}
+
+/*****************************************************************************/
+
+int gpu_context_t::gralloc_close(struct hw_device_t *dev)
+{
+    gpu_context_t* ctx = reinterpret_cast<gpu_context_t*>(dev);
+    if (ctx) {
+        /* TODO: keep a list of all buffer_handle_t created, and free them
+         * all here.
+         */
+        delete ctx;
+    }
+    return 0;
+}
+
diff --git a/sdm845/libgralloc/gpu.h b/sdm845/libgralloc/gpu.h
new file mode 100644
index 0000000..2248d30
--- /dev/null
+++ b/sdm845/libgralloc/gpu.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GRALLOC_GPU_H_
+#define GRALLOC_GPU_H_
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cutils/log.h>
+
+#include "gralloc_priv.h"
+#include "fb_priv.h"
+
+namespace gralloc {
+class IAllocController;
+class gpu_context_t : public alloc_device_t {
+    public:
+    gpu_context_t(const private_module_t* module,
+                  IAllocController* alloc_ctrl);
+
+    int gralloc_alloc_buffer(unsigned int size, int usage,
+                             buffer_handle_t* pHandle,
+                             int bufferType, int format,
+                             int width, int height);
+
+    int free_impl(private_handle_t const* hnd);
+
+    int alloc_impl(int w, int h, int format, int usage,
+                   buffer_handle_t* pHandle, int* pStride,
+                   unsigned int bufferSize = 0);
+
+    static int gralloc_alloc(alloc_device_t* dev, int w, int h,
+                             int format, int usage,
+                             buffer_handle_t* pHandle,
+                             int* pStride);
+    int gralloc_alloc_framebuffer_locked(int usage,
+                                         buffer_handle_t* pHandle);
+
+    int gralloc_alloc_framebuffer(int usage,
+                                  buffer_handle_t* pHandle);
+
+    static int gralloc_free(alloc_device_t* dev, buffer_handle_t handle);
+
+    static int gralloc_alloc_size(alloc_device_t* dev,
+                                  int w, int h, int format,
+                                  int usage, buffer_handle_t* pHandle,
+                                  int* pStride, int bufferSize);
+
+    static int gralloc_close(struct hw_device_t *dev);
+
+    private:
+   IAllocController* mAllocCtrl;
+    void getGrallocInformationFromFormat(int inputFormat,
+                                         int *bufferType);
+};
+}
+#endif  // GRALLOC_GPU_H
diff --git a/sdm845/libgralloc/gr.h b/sdm845/libgralloc/gr.h
new file mode 100644
index 0000000..dad4a38
--- /dev/null
+++ b/sdm845/libgralloc/gr.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2011 - 2017, The Linux Foundation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GR_H_
+#define GR_H_
+
+#include <stdint.h>
+#include <limits.h>
+#include <sys/cdefs.h>
+#include <hardware/gralloc.h>
+#include <pthread.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <cutils/native_handle.h>
+#include <utils/Singleton.h>
+#include "adreno_utils.h"
+
+/*****************************************************************************/
+
+struct private_module_t;
+struct private_handle_t;
+
+inline unsigned int roundUpToPageSize(unsigned int x) {
+    return (x + (getpagesize()-1)) & ~(getpagesize()-1);
+}
+
+template <class Type>
+inline Type ALIGN(Type x, Type align) {
+    return (x + align-1) & ~(align-1);
+}
+
+#define FALSE 0
+#define TRUE  1
+
+int mapFrameBufferLocked(struct private_module_t* module);
+int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd);
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
+        int usage, int& alignedw, int &alignedh);
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
+        int& alignedw, int &alignedh);
+
+int decideBufferHandlingMechanism(int format, const char *compositionUsed,
+                                  int hasBlitEngine, int *needConversion,
+                                  int *useBufferDirectly);
+
+// Allocate buffer from width, height, format into a private_handle_t
+// It is the responsibility of the caller to free the buffer
+int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage);
+void free_buffer(private_handle_t *hnd);
+int getYUVPlaneInfo(private_handle_t* pHnd, struct android_ycbcr* ycbcr);
+int getRgbDataAddress(private_handle_t* pHnd, void** rgb_data);
+
+// To query if UBWC is enabled, based on format and usage flags
+bool isUBwcEnabled(int format, int usage);
+
+// Function to check if the format is an RGB format
+bool isUncompressedRgbFormat(int format);
+
+// Returns number of planes, stride and offset of each plane for a given w,h,f
+int getBufferLayout(private_handle_t *hnd, uint32_t stride[4],
+        uint32_t offset[4], uint32_t *num_planes);
+/*****************************************************************************/
+
+class Locker {
+    pthread_mutex_t mutex;
+    pthread_cond_t cond;
+    public:
+    class Autolock {
+        Locker& locker;
+        public:
+        inline Autolock(Locker& locker) : locker(locker) {  locker.lock(); }
+        inline ~Autolock() { locker.unlock(); }
+    };
+    inline Locker()        {
+        pthread_mutex_init(&mutex, 0);
+        pthread_cond_init(&cond, 0);
+    }
+    inline ~Locker()       {
+        pthread_mutex_destroy(&mutex);
+        pthread_cond_destroy(&cond);
+    }
+    inline void lock()     { pthread_mutex_lock(&mutex); }
+    inline void wait()     { pthread_cond_wait(&cond, &mutex); }
+    inline void unlock()   { pthread_mutex_unlock(&mutex); }
+    inline void signal()   { pthread_cond_signal(&cond); }
+};
+
+
+class AdrenoMemInfo : public android::Singleton <AdrenoMemInfo>
+{
+    public:
+    AdrenoMemInfo();
+
+    ~AdrenoMemInfo();
+
+    /*
+     * Function to compute aligned width and aligned height based on
+     * width, height, format and usage flags.
+     *
+     * @return aligned width, aligned height
+     */
+    void getAlignedWidthAndHeight(int width, int height, int format,
+                            int usage, int& aligned_w, int& aligned_h);
+
+    /*
+     * Function to compute aligned width and aligned height based on
+     * private handle
+     *
+     * @return aligned width, aligned height
+     */
+    void getAlignedWidthAndHeight(const private_handle_t *hnd, int& aligned_w, int& aligned_h);
+
+    /*
+     * Function to compute the adreno aligned width and aligned height
+     * based on the width and format.
+     *
+     * @return aligned width, aligned height
+     */
+    void getGpuAlignedWidthHeight(int width, int height, int format,
+                            int tileEnabled, int& alignedw, int &alignedh);
+
+    /*
+     * Function to compute unaligned width and unaligned height based on
+     * private handle
+     *
+     * @return unaligned width, unaligned height
+     */
+    void getUnalignedWidthAndHeight(const private_handle_t *hnd, int& unaligned_w,
+                            int& unaligned_h);
+    /*
+     * Function to query whether GPU supports UBWC for given HAL format
+     * @return > 0 : supported
+     *           0 : not supported
+     */
+    int isUBWCSupportedByGPU(int format);
+
+    /*
+     * Function to get the corresponding Adreno format for given HAL format
+     */
+    ADRENOPIXELFORMAT getGpuPixelFormat(int hal_format);
+
+    private:
+        // Overriding flag to disable UBWC alloc for graphics stack
+        int  gfx_ubwc_disable;
+        // Pointer to the padding library.
+        void *libadreno_utils;
+
+        // link(s)to adreno surface padding library.
+        int (*LINK_adreno_compute_padding) (int width, int bpp,
+                                                int surface_tile_height,
+                                                int screen_tile_height,
+                                                int padding_threshold);
+
+        void (*LINK_adreno_compute_aligned_width_and_height) (int width,
+                                                int height,
+                                                int bpp,
+                                                int tile_mode,
+                                                int raster_mode,
+                                                int padding_threshold,
+                                                int *aligned_w,
+                                                int *aligned_h);
+
+        void(*LINK_adreno_compute_compressedfmt_aligned_width_and_height)(
+                                                int width,
+                                                int height,
+                                                int format,
+                                                int tile_mode,
+                                                int raster_mode,
+                                                int padding_threshold,
+                                                int *aligned_w,
+                                                int *aligned_h,
+                                                int *bpp);
+
+        int (*LINK_adreno_isUBWCSupportedByGpu) (ADRENOPIXELFORMAT format);
+
+        unsigned int (*LINK_adreno_get_gpu_pixel_alignment) ();
+};
+
+
+class MDPCapabilityInfo : public android::Singleton <MDPCapabilityInfo>
+{
+    int isUBwcSupported = 0;
+    int isWBUBWCSupported = 0;
+
+    public:
+        MDPCapabilityInfo();
+        /*
+        * Function to return whether MDP supports UBWC feature
+        *
+        * @return  1 : supported
+        *          0 : not supported
+        */
+        int isUBwcSupportedByMDP() { return isUBwcSupported; }
+        /*
+        * Function to return whether MDP WB block outputs UBWC format
+        *
+        * @return  1 : supported
+        *          0 : not supported
+        */
+        int isWBUBWCSupportedByMDP() { return isWBUBWCSupported; }
+};
+
+#endif /* GR_H_ */
diff --git a/sdm845/libgralloc/gralloc.cpp b/sdm845/libgralloc/gralloc.cpp
new file mode 100644
index 0000000..237b8a8
--- /dev/null
+++ b/sdm845/libgralloc/gralloc.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2008, The Android Open Source Project
+ * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <cutils/properties.h>
+
+#include "gr.h"
+#include "gpu.h"
+#include "memalloc.h"
+#include "alloc_controller.h"
+
+using namespace gralloc;
+
+int fb_device_open(const hw_module_t* module, const char* name,
+                   hw_device_t** device);
+
+static int gralloc_device_open(const hw_module_t* module, const char* name,
+                               hw_device_t** device);
+
+extern int gralloc_lock(gralloc_module_t const* module,
+                        buffer_handle_t handle, int usage,
+                        int l, int t, int w, int h,
+                        void** vaddr);
+
+extern int gralloc_lock_ycbcr(gralloc_module_t const* module,
+                        buffer_handle_t handle, int usage,
+                        int l, int t, int w, int h,
+                        struct android_ycbcr *ycbcr);
+
+extern int gralloc_unlock(gralloc_module_t const* module,
+                          buffer_handle_t handle);
+
+extern int gralloc_register_buffer(gralloc_module_t const* module,
+                                   buffer_handle_t handle);
+
+extern int gralloc_unregister_buffer(gralloc_module_t const* module,
+                                     buffer_handle_t handle);
+
+extern int gralloc_perform(struct gralloc_module_t const* module,
+                           int operation, ... );
+
+// HAL module methods
+static struct hw_module_methods_t gralloc_module_methods = {
+    .open = gralloc_device_open
+};
+
+// HAL module initialize
+struct private_module_t HAL_MODULE_INFO_SYM = {
+    .base = {
+        .common = {
+            .tag = HARDWARE_MODULE_TAG,
+            .version_major = 1,
+            .version_minor = 0,
+            .id = GRALLOC_HARDWARE_MODULE_ID,
+            .name = "Graphics Memory Allocator Module",
+            .author = "The Android Open Source Project",
+            .methods = &gralloc_module_methods,
+            .dso = 0,
+            .reserved = {0},
+        },
+        .registerBuffer = gralloc_register_buffer,
+        .unregisterBuffer = gralloc_unregister_buffer,
+        .lock = gralloc_lock,
+        .unlock = gralloc_unlock,
+        .perform = gralloc_perform,
+        .lock_ycbcr = gralloc_lock_ycbcr,
+    },
+    .framebuffer = 0,
+    .fbFormat = 0,
+    .flags = 0,
+    .numBuffers = 0,
+    .bufferMask = 0,
+    .lock = PTHREAD_MUTEX_INITIALIZER,
+};
+
+// Open Gralloc device
+int gralloc_device_open(const hw_module_t* module, const char* name,
+                        hw_device_t** device)
+{
+    int status = -EINVAL;
+    if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
+        const private_module_t* m = reinterpret_cast<const private_module_t*>(
+            module);
+        gpu_context_t *dev;
+        IAllocController* alloc_ctrl = IAllocController::getInstance();
+        dev = new gpu_context_t(m, alloc_ctrl);
+        if(!dev)
+            return status;
+
+        *device = &dev->common;
+        status = 0;
+    } else {
+        status = fb_device_open(module, name, device);
+    }
+    return status;
+}
diff --git a/sdm845/libgralloc/gralloc_priv.h b/sdm845/libgralloc/gralloc_priv.h
new file mode 100644
index 0000000..0f1f97a
--- /dev/null
+++ b/sdm845/libgralloc/gralloc_priv.h
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2011 - 2017, The Linux Foundation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GRALLOC_PRIV_H_
+#define GRALLOC_PRIV_H_
+
+#include <stdint.h>
+#include <limits.h>
+#include <sys/cdefs.h>
+#include <hardware/gralloc.h>
+#include <pthread.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <cutils/native_handle.h>
+
+#include <cutils/log.h>
+
+#define ROUND_UP_PAGESIZE(x) (unsigned int)( ((x) + getpagesize()-1)  & \
+                                             (~(getpagesize()-1)) )
+
+/* Gralloc usage bits indicating the type of allocation that should be used */
+/* SYSTEM heap comes from kernel vmalloc (ION_SYSTEM_HEAP_ID)
+ * is cached by default and
+ * is not secured */
+
+/* GRALLOC_USAGE_PRIVATE_0 is unused */
+
+/* Non linear, Universal Bandwidth Compression */
+#define GRALLOC_USAGE_PRIVATE_ALLOC_UBWC      GRALLOC_USAGE_PRIVATE_1
+
+/* IOMMU heap comes from manually allocated pages, can be cached/uncached,
+ * is not secured */
+#define GRALLOC_USAGE_PRIVATE_IOMMU_HEAP      GRALLOC_USAGE_PRIVATE_2
+
+/* MM heap is a carveout heap for video, can be secured */
+#define GRALLOC_USAGE_PRIVATE_MM_HEAP         GRALLOC_USAGE_PRIVATE_3
+
+/* ADSP heap is a carveout heap, is not secured */
+#define GRALLOC_USAGE_PRIVATE_ADSP_HEAP       0x01000000
+
+/* Set this for allocating uncached memory (using O_DSYNC),
+ * cannot be used with noncontiguous heaps */
+#define GRALLOC_USAGE_PRIVATE_UNCACHED        0x02000000
+
+/* Buffer content should be displayed on an primary display only */
+#define GRALLOC_USAGE_PRIVATE_INTERNAL_ONLY   0x04000000
+
+/* Buffer content should be displayed on an external display only */
+#define GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY   0x08000000
+
+/* This flag is set for WFD usecase */
+#define GRALLOC_USAGE_PRIVATE_WFD             0x00200000
+
+/* CAMERA heap is a carveout heap for camera, is not secured */
+#define GRALLOC_USAGE_PRIVATE_CAMERA_HEAP     0x00400000
+
+/* This flag is used for SECURE display usecase */
+#define GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY  0x00800000
+
+/* define Gralloc perform */
+#define GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER 1
+// This will be used by the graphics drivers to know if certain features
+// are defined in this display HAL.
+// Ex: Newer GFX libraries + Older Display HAL
+#define GRALLOC_MODULE_PERFORM_GET_STRIDE 2
+#define GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE 3
+#define GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE 4
+#define GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES 5
+#define GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE 6
+#define GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO 7
+#define GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO 8
+#define GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG 9
+#define GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS 10
+#define GRALLOC_MODULE_PERFORM_GET_IGC 11
+#define GRALLOC_MODULE_PERFORM_SET_IGC 12
+#define GRALLOC_MODULE_PERFORM_SET_SINGLE_BUFFER_MODE 13
+
+/* OEM specific HAL formats */
+
+#define HAL_PIXEL_FORMAT_RGBA_5551               6
+#define HAL_PIXEL_FORMAT_RGBA_4444               7
+#define HAL_PIXEL_FORMAT_NV12_ENCODEABLE         0x102
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS      0x7FA30C04
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED      0x7FA30C03
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP            0x109
+#define HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO     0x7FA30C01
+#define HAL_PIXEL_FORMAT_YCrCb_422_SP            0x10B
+#define HAL_PIXEL_FORMAT_R_8                     0x10D
+#define HAL_PIXEL_FORMAT_RG_88                   0x10E
+#define HAL_PIXEL_FORMAT_YCbCr_444_SP            0x10F
+#define HAL_PIXEL_FORMAT_YCrCb_444_SP            0x110
+#define HAL_PIXEL_FORMAT_YCrCb_422_I             0x111
+#define HAL_PIXEL_FORMAT_BGRX_8888               0x112
+#define HAL_PIXEL_FORMAT_NV21_ZSL                0x113
+#define HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS      0x114
+#define HAL_PIXEL_FORMAT_BGR_565                 0x115
+#define HAL_PIXEL_FORMAT_RGBA_1010102            0x116
+#define HAL_PIXEL_FORMAT_ARGB_2101010            0x117
+#define HAL_PIXEL_FORMAT_RGBX_1010102            0x118
+#define HAL_PIXEL_FORMAT_XRGB_2101010            0x119
+#define HAL_PIXEL_FORMAT_BGRA_1010102            0x11A
+#define HAL_PIXEL_FORMAT_ABGR_2101010            0x11B
+#define HAL_PIXEL_FORMAT_BGRX_1010102            0x11C
+#define HAL_PIXEL_FORMAT_XBGR_2101010            0x11D
+#define HAL_PIXEL_FORMAT_YCbCr_420_P010          0x11F
+#define HAL_PIXEL_FORMAT_CbYCrY_422_I            0x120
+#define HAL_PIXEL_FORMAT_BGR_888                 0x121
+#define HAL_PIXEL_FORMAT_RAW8                    0x123
+#define HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC     0x124
+
+#define HAL_PIXEL_FORMAT_INTERLACE               0x180
+
+//v4l2_fourcc('Y', 'U', 'Y', 'L'). 24 bpp YUYV 4:2:2 10 bit per component
+#define HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT       0x4C595559
+
+//v4l2_fourcc('Y', 'B', 'W', 'C'). 10 bit per component. This compressed
+//format reduces the memory access bandwidth
+#define HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT_COMPRESSED  0x43574259
+
+// UBWC aligned Venus format
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC 0x7FA30C06
+#define HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC     0x7FA30C09
+
+//Khronos ASTC formats
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR             0x93B0
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR             0x93B1
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR             0x93B2
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR             0x93B3
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR             0x93B4
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR             0x93B5
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR             0x93B6
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR             0x93B7
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR            0x93B8
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR            0x93B9
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR            0x93BA
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR           0x93BB
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR           0x93BC
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR           0x93BD
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR     0x93D0
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR     0x93D1
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR     0x93D2
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR     0x93D3
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR     0x93D4
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR     0x93D5
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR     0x93D6
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR     0x93D7
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR    0x93D8
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR    0x93D9
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR    0x93DA
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR   0x93DB
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR   0x93DC
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR   0x93DD
+
+/* possible values for inverse gamma correction */
+#define HAL_IGC_NOT_SPECIFIED     0
+#define HAL_IGC_s_RGB             1
+
+/* Color Space: Values maps to ColorSpace_t in qdMetadata.h */
+#define HAL_CSC_ITU_R_601         0
+#define HAL_CSC_ITU_R_601_FR      1
+#define HAL_CSC_ITU_R_709         2
+#define HAL_CSC_ITU_R_2020        3
+#define HAL_CSC_ITU_R_2020_FR     4
+
+/* possible formats for 3D content*/
+enum {
+    HAL_NO_3D                      = 0x0,
+    HAL_3D_SIDE_BY_SIDE_L_R        = 0x1,
+    HAL_3D_SIDE_BY_SIDE_R_L        = 0x2,
+    HAL_3D_TOP_BOTTOM              = 0x4,
+    HAL_3D_IN_SIDE_BY_SIDE_L_R     = 0x10000, //unused legacy format
+};
+
+enum {
+    BUFFER_TYPE_UI = 0,
+    BUFFER_TYPE_VIDEO
+};
+
+#ifdef __cplusplus
+struct private_handle_t : public native_handle {
+#else
+    struct private_handle_t {
+        native_handle_t nativeHandle;
+#endif
+        enum {
+            PRIV_FLAGS_FRAMEBUFFER        = 0x00000001,
+            PRIV_FLAGS_USES_ION           = 0x00000008,
+            PRIV_FLAGS_USES_ASHMEM        = 0x00000010,
+            PRIV_FLAGS_NEEDS_FLUSH        = 0x00000020,
+            PRIV_FLAGS_INTERNAL_ONLY      = 0x00000040,
+            PRIV_FLAGS_NON_CPU_WRITER     = 0x00000080,
+            PRIV_FLAGS_NONCONTIGUOUS_MEM  = 0x00000100,
+            PRIV_FLAGS_CACHED             = 0x00000200,
+            PRIV_FLAGS_SECURE_BUFFER      = 0x00000400,
+            // Display on external only
+            PRIV_FLAGS_EXTERNAL_ONLY      = 0x00002000,
+            // Set by HWC for protected non secure buffers
+            PRIV_FLAGS_PROTECTED_BUFFER   = 0x00004000,
+            PRIV_FLAGS_VIDEO_ENCODER      = 0x00010000,
+            PRIV_FLAGS_CAMERA_WRITE       = 0x00020000,
+            PRIV_FLAGS_CAMERA_READ        = 0x00040000,
+            PRIV_FLAGS_HW_COMPOSER        = 0x00080000,
+            PRIV_FLAGS_HW_TEXTURE         = 0x00100000,
+            PRIV_FLAGS_ITU_R_601          = 0x00200000, //Unused from display
+            PRIV_FLAGS_ITU_R_601_FR       = 0x00400000, //Unused from display
+            PRIV_FLAGS_ITU_R_709          = 0x00800000, //Unused from display
+            PRIV_FLAGS_SECURE_DISPLAY     = 0x01000000,
+            // Buffer is rendered in Tile Format
+            PRIV_FLAGS_TILE_RENDERED      = 0x02000000,
+            // Buffer rendered using CPU/SW renderer
+            PRIV_FLAGS_CPU_RENDERED       = 0x04000000,
+            // Buffer is allocated with UBWC alignment
+            PRIV_FLAGS_UBWC_ALIGNED       = 0x08000000,
+            // Buffer allocated will be consumed by SF/HWC
+            PRIV_FLAGS_DISP_CONSUMER      = 0x10000000
+        };
+
+        // file-descriptors
+        int     fd;
+        int     fd_metadata;          // fd for the meta-data
+        // ints
+        int     magic;
+        int     flags;
+        unsigned int  size;
+        unsigned int  offset;
+        int     bufferType;
+        uint64_t base __attribute__((aligned(8)));
+        unsigned int  offset_metadata;
+        // The gpu address mapped into the mmu.
+        uint64_t gpuaddr __attribute__((aligned(8)));
+        int     format;
+        int     width;   // holds aligned width of the actual buffer allocated
+        int     height;  // holds aligned height of the  actual buffer allocated
+        uint64_t base_metadata __attribute__((aligned(8)));
+        int unaligned_width;   // holds width client asked to allocate
+        int unaligned_height;  // holds height client asked to allocate
+
+#ifdef __cplusplus
+        static const int sNumFds = 2;
+        static inline int sNumInts() {
+            return ((sizeof(private_handle_t) - sizeof(native_handle_t)) /
+                    sizeof(int)) - sNumFds;
+        }
+        static const int sMagic = 'gmsm';
+
+        private_handle_t(int fd, unsigned int size, int flags, int bufferType,
+                int format, int width, int height) :
+            fd(fd), fd_metadata(-1), magic(sMagic),
+            flags(flags), size(size), offset(0), bufferType(bufferType),
+            base(0), offset_metadata(0), gpuaddr(0),
+            format(format), width(width), height(height),
+            base_metadata(0), unaligned_width(width),
+            unaligned_height(height)
+        {
+            version = (int) sizeof(native_handle);
+            numInts = sNumInts();
+            numFds = sNumFds;
+        }
+
+        private_handle_t(int fd, unsigned int size, int flags, int bufferType,
+                int format, int width, int height,
+                int eFd, unsigned int eOffset, uint64_t eBase) :
+            private_handle_t(fd, size, flags, bufferType, format, width, height)
+        {
+            fd_metadata = eFd;
+            offset_metadata = eOffset;
+            base_metadata = eBase;
+        }
+
+        private_handle_t(int fd, unsigned int size, int flags, int bufferType,
+                int format, int width, int height,
+                int eFd, unsigned int eOffset, uint64_t eBase,
+                int unaligned_w, int unaligned_h) :
+            private_handle_t(fd, size, flags, bufferType, format, width, height,
+                    eFd, eOffset, eBase)
+        {
+            unaligned_width = unaligned_w;
+            unaligned_height = unaligned_h;
+        }
+
+        ~private_handle_t() {
+            magic = 0;
+        }
+
+        static int validate(const native_handle* h) {
+            const private_handle_t* hnd = (const private_handle_t*)h;
+            if (!h || h->version != sizeof(native_handle) ||
+                h->numInts != sNumInts() || h->numFds != sNumFds ||
+                hnd->magic != sMagic)
+            {
+                ALOGD("Invalid gralloc handle (at %p): "
+                      "ver(%d/%zu) ints(%d/%d) fds(%d/%d)"
+                      "magic(%c%c%c%c/%c%c%c%c)",
+                      h,
+                      h ? h->version : -1, sizeof(native_handle),
+                      h ? h->numInts : -1, sNumInts(),
+                      h ? h->numFds : -1, sNumFds,
+                      hnd ? (((hnd->magic >> 24) & 0xFF)?
+                             ((hnd->magic >> 24) & 0xFF) : '-') : '?',
+                      hnd ? (((hnd->magic >> 16) & 0xFF)?
+                             ((hnd->magic >> 16) & 0xFF) : '-') : '?',
+                      hnd ? (((hnd->magic >> 8) & 0xFF)?
+                             ((hnd->magic >> 8) & 0xFF) : '-') : '?',
+                      hnd ? (((hnd->magic >> 0) & 0xFF)?
+                             ((hnd->magic >> 0) & 0xFF) : '-') : '?',
+                      (sMagic >> 24) & 0xFF,
+                      (sMagic >> 16) & 0xFF,
+                      (sMagic >> 8) & 0xFF,
+                      (sMagic >> 0) & 0xFF);
+                return -EINVAL;
+            }
+            return 0;
+        }
+
+        static private_handle_t* dynamicCast(const native_handle* in) {
+            if (validate(in) == 0) {
+                return (private_handle_t*) in;
+            }
+            return NULL;
+        }
+#endif
+    };
+
+#endif /* GRALLOC_PRIV_H_ */
diff --git a/sdm845/libgralloc/ionalloc.cpp b/sdm845/libgralloc/ionalloc.cpp
new file mode 100644
index 0000000..329e30f
--- /dev/null
+++ b/sdm845/libgralloc/ionalloc.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2011-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.
+ */
+
+#define DEBUG 0
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <cutils/log.h>
+#include <errno.h>
+#include <utils/Trace.h>
+#include <cutils/trace.h>
+#include "gralloc_priv.h"
+#include "ionalloc.h"
+
+using gralloc::IonAlloc;
+
+#define ION_DEVICE "/dev/ion"
+
+int IonAlloc::open_device()
+{
+    if(mIonFd == FD_INIT)
+        mIonFd = open(ION_DEVICE, O_RDONLY);
+
+    if(mIonFd < 0 ) {
+        ALOGE("%s: Failed to open ion device - %s",
+              __FUNCTION__, strerror(errno));
+        mIonFd = FD_INIT;
+        return -errno;
+    }
+    return 0;
+}
+
+void IonAlloc::close_device()
+{
+    if(mIonFd >= 0)
+        close(mIonFd);
+    mIonFd = FD_INIT;
+}
+
+int IonAlloc::alloc_buffer(alloc_data& data)
+{
+    ATRACE_CALL();
+    Locker::Autolock _l(mLock);
+    int err = 0;
+    struct ion_handle_data handle_data;
+    struct ion_fd_data fd_data;
+    struct ion_allocation_data ionAllocData;
+    void *base = 0;
+
+    ionAllocData.len = data.size;
+    ionAllocData.align = data.align;
+    ionAllocData.heap_id_mask = data.heapId;
+    ionAllocData.flags = data.flags;
+    ionAllocData.flags |= data.uncached ? 0 : ION_FLAG_CACHED;
+    err = open_device();
+    if (err)
+        return err;
+    if(ioctl(mIonFd, ION_IOC_ALLOC, &ionAllocData)) {
+        err = -errno;
+        ALOGE("ION_IOC_ALLOC failed with error - %s", strerror(errno));
+        return err;
+    }
+
+    fd_data.handle = ionAllocData.handle;
+    handle_data.handle = ionAllocData.handle;
+    if(ioctl(mIonFd, ION_IOC_MAP, &fd_data)) {
+        err = -errno;
+        ALOGE("%s: ION_IOC_MAP failed with error - %s",
+              __FUNCTION__, strerror(errno));
+        ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+        return err;
+    }
+
+    if(!(data.flags & ION_SECURE)) {
+        base = mmap(0, ionAllocData.len, PROT_READ|PROT_WRITE,
+                    MAP_SHARED, fd_data.fd, 0);
+        if(base == MAP_FAILED) {
+            err = -errno;
+            ALOGE("%s: Failed to map the allocated memory: %s",
+                  __FUNCTION__, strerror(errno));
+            ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+            return err;
+        }
+    }
+
+    data.base = base;
+    data.fd = fd_data.fd;
+    ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+    ALOGD_IF(DEBUG, "ion: Allocated buffer base:%p size:%zu fd:%d",
+          data.base, ionAllocData.len, data.fd);
+    return 0;
+}
+
+
+int IonAlloc::free_buffer(void* base, unsigned int size, unsigned int offset,
+        int fd)
+{
+    ATRACE_CALL();
+    Locker::Autolock _l(mLock);
+    ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%u fd:%d",
+          base, size, fd);
+    int err = 0;
+    err = open_device();
+    if (err)
+        return err;
+
+    if(base)
+        err = unmap_buffer(base, size, offset);
+    close(fd);
+    return err;
+}
+
+int IonAlloc::map_buffer(void **pBase, unsigned int size, unsigned int offset,
+        int fd)
+{
+    ATRACE_CALL();
+    int err = 0;
+    void *base = 0;
+    // It is a (quirky) requirement of ION to have opened the
+    // ion fd in the process that is doing the mapping
+    err = open_device();
+    if (err)
+        return err;
+
+    base = mmap(0, size, PROT_READ| PROT_WRITE,
+                MAP_SHARED, fd, 0);
+    *pBase = base;
+    if(base == MAP_FAILED) {
+        err = -errno;
+        ALOGE("ion: Failed to map memory in the client: %s",
+              strerror(errno));
+    } else {
+        ALOGD_IF(DEBUG, "ion: Mapped buffer base:%p size:%u offset:%u fd:%d",
+              base, size, offset, fd);
+    }
+    return err;
+}
+
+int IonAlloc::unmap_buffer(void *base, unsigned int size,
+        unsigned int /*offset*/)
+{
+    ATRACE_CALL();
+    ALOGD_IF(DEBUG, "ion: Unmapping buffer  base:%p size:%u", base, size);
+    int err = 0;
+    if(munmap(base, size)) {
+        err = -errno;
+        ALOGE("ion: Failed to unmap memory at %p : %s",
+              base, strerror(errno));
+    }
+    return err;
+
+}
+int IonAlloc::clean_buffer(void *base, unsigned int size, unsigned int offset,
+        int fd, int op)
+{
+    ATRACE_CALL();
+    ATRACE_INT("operation id", op);
+    struct ion_flush_data flush_data;
+    struct ion_fd_data fd_data;
+    struct ion_handle_data handle_data;
+    int err = 0;
+
+    err = open_device();
+    if (err)
+        return err;
+
+    fd_data.fd = fd;
+    if (ioctl(mIonFd, ION_IOC_IMPORT, &fd_data)) {
+        err = -errno;
+        ALOGE("%s: ION_IOC_IMPORT failed with error - %s",
+              __FUNCTION__, strerror(errno));
+        return err;
+    }
+
+    handle_data.handle = fd_data.handle;
+    flush_data.handle  = fd_data.handle;
+    flush_data.vaddr   = base;
+    // offset and length are unsigned int
+    flush_data.offset  = offset;
+    flush_data.length  = size;
+
+    struct ion_custom_data d;
+    switch(op) {
+    case CACHE_CLEAN:
+        d.cmd = ION_IOC_CLEAN_CACHES;
+        break;
+    case CACHE_INVALIDATE:
+            d.cmd = ION_IOC_INV_CACHES;
+        break;
+    case CACHE_CLEAN_AND_INVALIDATE:
+    default:
+        d.cmd = ION_IOC_CLEAN_INV_CACHES;
+    }
+
+    d.arg = (unsigned long int)&flush_data;
+
+    if(ioctl(mIonFd, ION_IOC_CUSTOM, &d)) {
+        err = -errno;
+        ALOGE("%s: ION_IOC_CLEAN_INV_CACHES failed with error - %s",
+
+              __FUNCTION__, strerror(errno));
+        ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+        return err;
+    }
+    ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+    return 0;
+}
+
diff --git a/sdm845/libgralloc/ionalloc.h b/sdm845/libgralloc/ionalloc.h
new file mode 100644
index 0000000..635bda5
--- /dev/null
+++ b/sdm845/libgralloc/ionalloc.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011-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 GRALLOC_IONALLOC_H
+#define GRALLOC_IONALLOC_H
+
+#include <linux/msm_ion.h>
+#include "memalloc.h"
+#include "gr.h"
+
+namespace gralloc {
+
+class IonAlloc : public IMemAlloc  {
+
+    public:
+    virtual int alloc_buffer(alloc_data& data);
+
+    virtual int free_buffer(void *base, unsigned int size,
+                            unsigned int offset, int fd);
+
+    virtual int map_buffer(void **pBase, unsigned int size,
+                           unsigned int offset, int fd);
+
+    virtual int unmap_buffer(void *base, unsigned int size,
+                             unsigned int offset);
+
+    virtual int clean_buffer(void*base, unsigned int size,
+                             unsigned int offset, int fd, int op);
+
+    IonAlloc() { mIonFd = FD_INIT; }
+
+    ~IonAlloc() { close_device(); }
+
+    private:
+    int mIonFd;
+
+    int open_device();
+
+    void close_device();
+
+    mutable Locker mLock;
+
+};
+
+}
+
+#endif /* GRALLOC_IONALLOC_H */
+
diff --git a/sdm845/libgralloc/mapper.cpp b/sdm845/libgralloc/mapper.cpp
new file mode 100644
index 0000000..acf5e2c
--- /dev/null
+++ b/sdm845/libgralloc/mapper.cpp
@@ -0,0 +1,523 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+#include <limits.h>
+#include <errno.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+#include <utils/Trace.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#include "gralloc_priv.h"
+#include "gr.h"
+#include "alloc_controller.h"
+#include "memalloc.h"
+#include <qdMetaData.h>
+
+
+using namespace gralloc;
+/*****************************************************************************/
+
+// Return the type of allocator -
+// these are used for mapping/unmapping
+static IMemAlloc* getAllocator(int flags)
+{
+    IMemAlloc* memalloc;
+    IAllocController* alloc_ctrl = IAllocController::getInstance();
+    memalloc = alloc_ctrl->getAllocator(flags);
+    return memalloc;
+}
+
+static int gralloc_map_metadata(buffer_handle_t handle) {
+    private_handle_t* hnd = (private_handle_t*)handle;
+    hnd->base_metadata = 0;
+    IMemAlloc* memalloc = getAllocator(hnd->flags) ;
+    void *mappedAddress = MAP_FAILED;
+    unsigned int size = 0;
+    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
+        mappedAddress = MAP_FAILED;
+        size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+        int ret = memalloc->map_buffer(&mappedAddress, size,
+                                       hnd->offset_metadata, hnd->fd_metadata);
+        if(ret || mappedAddress == MAP_FAILED) {
+            ALOGE("Could not mmap metadata for handle %p, fd=%d (%s)",
+                  hnd, hnd->fd_metadata, strerror(errno));
+            return -errno;
+        }
+        hnd->base_metadata = uint64_t(mappedAddress) + hnd->offset_metadata;
+    }
+    return 0;
+}
+
+static int gralloc_map(gralloc_module_t const* module,
+                       buffer_handle_t handle)
+{
+    ATRACE_CALL();
+    if(!module)
+        return -EINVAL;
+
+    private_handle_t* hnd = (private_handle_t*)handle;
+    unsigned int size = 0;
+    int err = 0;
+    IMemAlloc* memalloc = getAllocator(hnd->flags) ;
+    void *mappedAddress = MAP_FAILED;
+    hnd->base = 0;
+
+    // Dont map framebuffer and secure buffers
+    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
+        !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
+        size = hnd->size;
+        err = memalloc->map_buffer(&mappedAddress, size,
+                                       hnd->offset, hnd->fd);
+        if(err || mappedAddress == MAP_FAILED) {
+            ALOGE("Could not mmap handle %p, fd=%d (%s)",
+                  handle, hnd->fd, strerror(errno));
+            return -errno;
+        }
+
+        hnd->base = uint64_t(mappedAddress) + hnd->offset;
+    } else {
+        // Cannot map secure buffers or framebuffers, but still need to map
+        // metadata for secure buffers.
+        // If mapping a secure buffers fails, the framework needs to get
+        // an error code.
+        err = -EACCES;
+    }
+
+    //Allow mapping of metadata for all buffers including secure ones, but not
+    //of framebuffer
+    int metadata_err = gralloc_map_metadata(handle);
+    if (!err) {
+        err = metadata_err;
+    }
+    return err;
+}
+
+static int gralloc_unmap(gralloc_module_t const* module,
+                         buffer_handle_t handle)
+{
+    ATRACE_CALL();
+    int err = -EINVAL;
+    if(!module)
+        return err;
+
+    private_handle_t* hnd = (private_handle_t*)handle;
+    IMemAlloc* memalloc = getAllocator(hnd->flags) ;
+    if(!memalloc)
+        return err;
+
+    if(hnd->base) {
+        err = memalloc->unmap_buffer((void*)hnd->base, hnd->size, hnd->offset);
+        if (err) {
+            ALOGE("Could not unmap memory at address %p, %s", (void*) hnd->base,
+                    strerror(errno));
+            return -errno;
+        }
+        hnd->base = 0;
+    }
+
+    if(hnd->base_metadata) {
+        unsigned int size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+        err = memalloc->unmap_buffer((void*)hnd->base_metadata,
+                size, hnd->offset_metadata);
+        if (err) {
+            ALOGE("Could not unmap memory at address %p, %s",
+                    (void*) hnd->base_metadata, strerror(errno));
+            return -errno;
+        }
+        hnd->base_metadata = 0;
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
+
+/*****************************************************************************/
+
+int gralloc_register_buffer(gralloc_module_t const* module,
+                            buffer_handle_t handle)
+{
+    ATRACE_CALL();
+    if (!module || private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    int err =  gralloc_map(module, handle);
+    /* Do not fail register_buffer for secure buffers*/
+    if (err == -EACCES)
+        err = 0;
+    return err;
+}
+
+int gralloc_unregister_buffer(gralloc_module_t const* module,
+                              buffer_handle_t handle)
+{
+    ATRACE_CALL();
+    if (!module || private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    /*
+     * If the buffer has been mapped during a lock operation, it's time
+     * to un-map it. It's an error to be here with a locked buffer.
+     * NOTE: the framebuffer is handled differently and is never unmapped.
+     * Also base and base_metadata are reset.
+     */
+    return gralloc_unmap(module, handle);
+}
+
+int terminateBuffer(gralloc_module_t const* module,
+                    private_handle_t* hnd)
+{
+    ATRACE_CALL();
+    if(!module)
+        return -EINVAL;
+
+    /*
+     * If the buffer has been mapped during a lock operation, it's time
+     * to un-map it. It's an error to be here with a locked buffer.
+     * NOTE: the framebuffer is handled differently and is never unmapped.
+     * Also base and base_metadata are reset.
+     */
+    return gralloc_unmap(module, hnd);
+}
+
+static int gralloc_map_and_invalidate (gralloc_module_t const* module,
+                                       buffer_handle_t handle, int usage)
+{
+    ATRACE_CALL();
+    if (!module || private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    int err = 0;
+    private_handle_t* hnd = (private_handle_t*)handle;
+    if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
+        if (hnd->base == 0) {
+            // we need to map for real
+            pthread_mutex_t* const lock = &sMapLock;
+            pthread_mutex_lock(lock);
+            err = gralloc_map(module, handle);
+            pthread_mutex_unlock(lock);
+        }
+        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION and
+                hnd->flags & private_handle_t::PRIV_FLAGS_CACHED) {
+            //Invalidate if CPU reads in software and there are non-CPU
+            //writers. No need to do this for the metadata buffer as it is
+            //only read/written in software.
+            if ((usage & GRALLOC_USAGE_SW_READ_MASK) and
+                    (hnd->flags & private_handle_t::PRIV_FLAGS_NON_CPU_WRITER))
+            {
+                IMemAlloc* memalloc = getAllocator(hnd->flags) ;
+                err = memalloc->clean_buffer((void*)hnd->base,
+                        hnd->size, hnd->offset, hnd->fd,
+                        CACHE_INVALIDATE);
+            }
+            //Mark the buffer to be flushed after CPU write.
+            if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
+                hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
+            }
+        }
+    }
+
+    return err;
+}
+
+int gralloc_lock(gralloc_module_t const* module,
+                 buffer_handle_t handle, int usage,
+                 int /*l*/, int /*t*/, int /*w*/, int /*h*/,
+                 void** vaddr)
+{
+    ATRACE_CALL();
+    private_handle_t* hnd = (private_handle_t*)handle;
+    int err = gralloc_map_and_invalidate(module, handle, usage);
+    if(!err)
+        *vaddr = (void*)hnd->base;
+    return err;
+}
+
+int gralloc_lock_ycbcr(gralloc_module_t const* module,
+                 buffer_handle_t handle, int usage,
+                 int /*l*/, int /*t*/, int /*w*/, int /*h*/,
+                 struct android_ycbcr *ycbcr)
+{
+    ATRACE_CALL();
+    private_handle_t* hnd = (private_handle_t*)handle;
+    int err = gralloc_map_and_invalidate(module, handle, usage);
+    if(!err)
+        err = getYUVPlaneInfo(hnd, ycbcr);
+    return err;
+}
+
+int gralloc_unlock(gralloc_module_t const* module,
+                   buffer_handle_t handle)
+{
+    ATRACE_CALL();
+    if (!module || private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    int err = 0;
+    private_handle_t* hnd = (private_handle_t*)handle;
+
+    IMemAlloc* memalloc = getAllocator(hnd->flags);
+    if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
+        err = memalloc->clean_buffer((void*)hnd->base,
+                hnd->size, hnd->offset, hnd->fd,
+                CACHE_CLEAN);
+        hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
+    }
+
+    return err;
+}
+
+/*****************************************************************************/
+
+int gralloc_perform(struct gralloc_module_t const* module,
+                    int operation, ... )
+{
+    int res = -EINVAL;
+    va_list args;
+    if(!module)
+        return res;
+
+    va_start(args, operation);
+    switch (operation) {
+        case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER:
+            {
+                int fd = va_arg(args, int);
+                unsigned int size = va_arg(args, unsigned int);
+                unsigned int offset = va_arg(args, unsigned int);
+                void* base = va_arg(args, void*);
+                int width = va_arg(args, int);
+                int height = va_arg(args, int);
+                int format = va_arg(args, int);
+                int alignedw = 0, alignedh = 0;
+
+                native_handle_t** handle = va_arg(args, native_handle_t**);
+                private_handle_t* hnd = (private_handle_t*)native_handle_create(
+                    private_handle_t::sNumFds, private_handle_t::sNumInts());
+                if (hnd) {
+                  hnd->magic = private_handle_t::sMagic;
+                  hnd->fd = fd;
+                  hnd->flags =  private_handle_t::PRIV_FLAGS_USES_ION;
+                  hnd->size = size;
+                  hnd->offset = offset;
+                  hnd->base = uint64_t(base) + offset;
+                  hnd->gpuaddr = 0;
+                  AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+                          height, format, 0, alignedw, alignedh);
+                  hnd->width = alignedw;
+                  hnd->height = alignedh;
+                  hnd->unaligned_width = width;
+                  hnd->unaligned_height = height;
+                  hnd->format = format;
+                  *handle = (native_handle_t *)hnd;
+                  res = 0;
+                }
+                break;
+
+            }
+        case GRALLOC_MODULE_PERFORM_GET_STRIDE:
+            {
+                int width   = va_arg(args, int);
+                int format  = va_arg(args, int);
+                int *stride = va_arg(args, int *);
+                int alignedw = 0, alignedh = 0;
+                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+                        0, format, 0, alignedw, alignedh);
+                *stride = alignedw;
+                res = 0;
+            } break;
+
+        case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE:
+            {
+                const private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                int *stride = va_arg(args, int *);
+                if (private_handle_t::validate(hnd)) {
+                    return res;
+                }
+
+                int alignedw = 0, alignedh = 0;
+                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
+                *stride = alignedw;
+
+                res = 0;
+            } break;
+
+        case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE:
+            {
+                const private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                int *stride = va_arg(args, int *);
+                int *height = va_arg(args, int *);
+                if (private_handle_t::validate(hnd)) {
+                    return res;
+                }
+
+                int alignedw = 0, alignedh = 0;
+                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
+                *stride = alignedw;
+                *height = alignedh;
+
+                res = 0;
+            } break;
+
+        case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES:
+            {
+                int width   = va_arg(args, int);
+                int height  = va_arg(args, int);
+                int format  = va_arg(args, int);
+                int usage   = va_arg(args, int);
+                int *alignedWidth = va_arg(args, int *);
+                int *alignedHeight = va_arg(args, int *);
+                int *tileEnabled = va_arg(args,int *);
+                *tileEnabled = isUBwcEnabled(format, usage);
+                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+                        height, format, usage, *alignedWidth, *alignedHeight);
+                res = 0;
+            } break;
+
+        case GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE:
+            {
+                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                int *color_space = va_arg(args, int *);
+                if (private_handle_t::validate(hnd)) {
+                    return res;
+                }
+                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+                if (!metadata) {
+                    break;
+#ifdef USE_COLOR_METADATA
+                } else if (metadata->operation & COLOR_METADATA) {
+                    ColorMetaData *colorMetadata = &metadata->color;
+                    res = 0;
+                    switch (colorMetadata->colorPrimaries) {
+                    case ColorPrimaries_BT709_5:
+                        *color_space = HAL_CSC_ITU_R_709;
+                        break;
+                    case ColorPrimaries_BT601_6_525:
+                        *color_space = ((colorMetadata->range) ?
+                                        HAL_CSC_ITU_R_601_FR : HAL_CSC_ITU_R_601);
+                        break;
+                    case ColorPrimaries_BT2020:
+                        *color_space = (colorMetadata->range) ?
+                            HAL_CSC_ITU_R_2020_FR : HAL_CSC_ITU_R_2020;
+                        break;
+                    default:
+                        res = -EINVAL;
+                        break;
+                    }
+#endif
+                } else if(metadata->operation & UPDATE_COLOR_SPACE) {
+                    *color_space = metadata->colorSpace;
+                    res = 0;
+                }
+            } break;
+
+        case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO:
+            {
+                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                android_ycbcr* ycbcr = va_arg(args, struct android_ycbcr *);
+                if (!private_handle_t::validate(hnd)) {
+                    res = getYUVPlaneInfo(hnd, ycbcr);
+                }
+            } break;
+
+        case GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO:
+            {
+                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                int *map_secure_buffer = va_arg(args, int *);
+                if (private_handle_t::validate(hnd)) {
+                    return res;
+                }
+                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+                if(metadata && metadata->operation & MAP_SECURE_BUFFER) {
+                    *map_secure_buffer = metadata->mapSecureBuffer;
+                    res = 0;
+                } else {
+                    *map_secure_buffer = 0;
+                }
+            } break;
+
+        case GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG:
+            {
+                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                int *flag = va_arg(args, int *);
+                if (private_handle_t::validate(hnd)) {
+                    return res;
+                }
+                *flag = hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+                if (metadata && (metadata->operation & LINEAR_FORMAT)) {
+                    *flag = 0;
+                }
+                res = 0;
+            } break;
+
+        case GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS:
+            {
+                private_handle_t* hnd = va_arg(args, private_handle_t*);
+                void** rgb_data = va_arg(args, void**);
+                if (!private_handle_t::validate(hnd)) {
+                    res = getRgbDataAddress(hnd, rgb_data);
+                }
+            } break;
+
+        case GRALLOC_MODULE_PERFORM_GET_IGC:
+            {
+                private_handle_t* hnd = va_arg(args, private_handle_t*);
+                uint32_t *igc = va_arg(args, uint32_t *);
+                if (!private_handle_t::validate(hnd) && igc) {
+                    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+                    if (metadata && (metadata->operation & SET_IGC)) {
+                        *igc = metadata->igc;
+                        res = 0;
+                    }
+                }
+            } break;
+
+        case GRALLOC_MODULE_PERFORM_SET_IGC:
+            res = 0;
+            break;
+
+        case GRALLOC_MODULE_PERFORM_SET_SINGLE_BUFFER_MODE:
+            {
+                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                uint32_t *enable = va_arg(args, uint32_t*);
+                if (!private_handle_t::validate(hnd)) {
+                    setMetaData(hnd, SET_SINGLE_BUFFER_MODE, enable);
+                    res = 0;
+                }
+            } break;
+        default:
+            break;
+    }
+    va_end(args);
+    return res;
+}
diff --git a/sdm845/libgralloc/memalloc.h b/sdm845/libgralloc/memalloc.h
new file mode 100644
index 0000000..598d983
--- /dev/null
+++ b/sdm845/libgralloc/memalloc.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2011-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 GRALLOC_MEMALLOC_H
+#define GRALLOC_MEMALLOC_H
+
+#include <stdlib.h>
+
+namespace gralloc {
+
+enum {
+    CACHE_CLEAN = 0x1,
+    CACHE_INVALIDATE,
+    CACHE_CLEAN_AND_INVALIDATE,
+};
+
+struct alloc_data {
+    void           *base;
+    int            fd;
+    unsigned int   offset;
+    unsigned int   size;
+    unsigned int   align;
+    uintptr_t      pHandle;
+    bool           uncached;
+    unsigned int   flags;
+    unsigned int   heapId;
+    int            allocType;
+};
+
+class IMemAlloc {
+
+    public:
+    // Allocate buffer - fill in the alloc_data
+    // structure and pass it in. Mapped address
+    // and fd are returned in the alloc_data struct
+    virtual int alloc_buffer(alloc_data& data) = 0;
+
+    // Free buffer
+    virtual int free_buffer(void *base, unsigned int size,
+                            unsigned int offset, int fd) = 0;
+
+    // Map buffer
+    virtual int map_buffer(void **pBase, unsigned int size,
+                           unsigned int offset, int fd) = 0;
+
+    // Unmap buffer
+    virtual int unmap_buffer(void *base, unsigned int size,
+                             unsigned int offset) = 0;
+
+    // Clean and invalidate
+    virtual int clean_buffer(void *base, unsigned int size,
+                             unsigned int offset, int fd, int op) = 0;
+
+    // Destructor
+    virtual ~IMemAlloc() {};
+
+    enum {
+        FD_INIT = -1,
+    };
+
+};
+
+} // end gralloc namespace
+#endif // GRALLOC_MEMALLOC_H
diff --git a/sdm845/libgralloc1/Android.mk b/sdm845/libgralloc1/Android.mk
new file mode 100644
index 0000000..cdb651c
--- /dev/null
+++ b/sdm845/libgralloc1/Android.mk
@@ -0,0 +1,38 @@
+# Gralloc module
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := gralloc.$(TARGET_BOARD_PLATFORM)
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_RELATIVE_PATH    := hw
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) \
+                                 external/libcxx/include/
+
+LOCAL_HEADER_LIBRARIES        := display_headers
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdMetaData libsync libgrallocutils
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wall -std=c++11 -Werror
+LOCAL_CFLAGS                  += -isystem  $(kernel_includes)
+LOCAL_CLANG                   := true
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
+LOCAL_SRC_FILES               := gr_ion_alloc.cpp \
+                                 gr_allocator.cpp \
+                                 gr_buf_mgr.cpp \
+                                 gr_device_impl.cpp
+LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
+LOCAL_COPY_HEADERS            := gr_device_impl.h gralloc_priv.h gr_priv_handle.h
+include $(BUILD_SHARED_LIBRARY)
+
+#libgrallocutils
+include $(CLEAR_VARS)
+LOCAL_MODULE                  := libgrallocutils
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_HEADER_LIBRARIES        := display_headers
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdMetaData libdl
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"grallocutils\" -Wno-sign-conversion
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
+LOCAL_SRC_FILES               := gr_utils.cpp gr_adreno_info.cpp
+include $(BUILD_SHARED_LIBRARY)
diff --git a/sdm845/libgralloc1/gr_adreno_info.cpp b/sdm845/libgralloc1/gr_adreno_info.cpp
new file mode 100644
index 0000000..ecac238
--- /dev/null
+++ b/sdm845/libgralloc1/gr_adreno_info.cpp
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2011-2017, 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/log.h>
+#include <cutils/properties.h>
+#include <dlfcn.h>
+#include <mutex>
+
+#include "gralloc_priv.h"
+#include "gr_adreno_info.h"
+#include "gr_utils.h"
+
+using std::lock_guard;
+using std::mutex;
+
+namespace gralloc1 {
+
+AdrenoMemInfo *AdrenoMemInfo::s_instance = nullptr;
+
+AdrenoMemInfo *AdrenoMemInfo::GetInstance() {
+  static mutex s_lock;
+  lock_guard<mutex> obj(s_lock);
+  if (!s_instance) {
+    s_instance = new AdrenoMemInfo();
+    if (!s_instance->Init()) {
+      delete s_instance;
+      s_instance = nullptr;
+    }
+  }
+
+  return s_instance;
+}
+
+bool AdrenoMemInfo::Init() {
+  libadreno_utils_ = ::dlopen("libadreno_utils.so", RTLD_NOW);
+  if (libadreno_utils_) {
+    *reinterpret_cast<void **>(&LINK_adreno_compute_aligned_width_and_height) =
+        ::dlsym(libadreno_utils_, "compute_aligned_width_and_height");
+    *reinterpret_cast<void **>(&LINK_adreno_compute_fmt_aligned_width_and_height) =
+        ::dlsym(libadreno_utils_, "compute_fmt_aligned_width_and_height");
+    *reinterpret_cast<void **>(&LINK_adreno_compute_padding) =
+        ::dlsym(libadreno_utils_, "compute_surface_padding");
+    *reinterpret_cast<void **>(&LINK_adreno_compute_compressedfmt_aligned_width_and_height) =
+        ::dlsym(libadreno_utils_, "compute_compressedfmt_aligned_width_and_height");
+    *reinterpret_cast<void **>(&LINK_adreno_isUBWCSupportedByGpu) =
+        ::dlsym(libadreno_utils_, "isUBWCSupportedByGpu");
+    *reinterpret_cast<void **>(&LINK_adreno_get_gpu_pixel_alignment) =
+        ::dlsym(libadreno_utils_, "get_gpu_pixel_alignment");
+  } else {
+    ALOGE(" Failed to load libadreno_utils.so");
+    return false;
+  }
+
+  // Check if the overriding property debug.gralloc.gfx_ubwc_disable
+  // that disables UBWC allocations for the graphics stack is set
+  char property[PROPERTY_VALUE_MAX];
+  property_get("debug.gralloc.gfx_ubwc_disable", property, "0");
+  if (!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
+      !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
+    gfx_ubwc_disable_ = true;
+  }
+
+  if ((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
+      (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
+       (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)))) {
+    map_fb_ = true;
+  }
+
+  return true;
+}
+
+AdrenoMemInfo::~AdrenoMemInfo() {
+  if (libadreno_utils_) {
+    ::dlclose(libadreno_utils_);
+  }
+}
+
+void AdrenoMemInfo::AlignUnCompressedRGB(int width, int height, int format, int tile_enabled,
+                                         unsigned int *aligned_w, unsigned int *aligned_h) {
+  *aligned_w = (unsigned int)ALIGN(width, 32);
+  *aligned_h = (unsigned int)ALIGN(height, 32);
+
+  // Don't add any additional padding if debug.gralloc.map_fb_memory
+  // is enabled
+  if (map_fb_) {
+    return;
+  }
+
+  int bpp = 4;
+  switch (format) {
+    case HAL_PIXEL_FORMAT_RGB_888:
+    case HAL_PIXEL_FORMAT_BGR_888:
+      bpp = 3;
+      break;
+    case HAL_PIXEL_FORMAT_RGB_565:
+    case HAL_PIXEL_FORMAT_BGR_565:
+    case HAL_PIXEL_FORMAT_RGBA_5551:
+    case HAL_PIXEL_FORMAT_RGBA_4444:
+      bpp = 2;
+      break;
+    default:
+      break;
+  }
+
+  int raster_mode = 0;          // Adreno unknown raster mode.
+  int padding_threshold = 512;  // Threshold for padding surfaces.
+  // the function below computes aligned width and aligned height
+  // based on linear or macro tile mode selected.
+  if (LINK_adreno_compute_fmt_aligned_width_and_height) {
+    // We call into adreno_utils only for RGB formats. So plane_id is 0 and
+    // num_samples is 1 always. We may  have to add uitility function to
+    // find out these if there is a need to call this API for YUV formats.
+    LINK_adreno_compute_fmt_aligned_width_and_height(
+        width, height, 0/*plane_id*/, GetGpuPixelFormat(format), 1/*num_samples*/,
+        tile_enabled, raster_mode, padding_threshold,
+        reinterpret_cast<int *>(aligned_w), reinterpret_cast<int *>(aligned_h));
+  } else if (LINK_adreno_compute_aligned_width_and_height) {
+    LINK_adreno_compute_aligned_width_and_height(
+        width, height, bpp, tile_enabled, raster_mode, padding_threshold,
+        reinterpret_cast<int *>(aligned_w), reinterpret_cast<int *>(aligned_h));
+  } else if (LINK_adreno_compute_padding) {
+    int surface_tile_height = 1;  // Linear surface
+    *aligned_w = UINT(LINK_adreno_compute_padding(width, bpp, surface_tile_height, raster_mode,
+                                                  padding_threshold));
+    ALOGW("%s: Warning!! Old GFX API is used to calculate stride", __FUNCTION__);
+  } else {
+    ALOGW(
+        "%s: Warning!! Symbols compute_surface_padding and "
+        "compute_fmt_aligned_width_and_height and "
+        "compute_aligned_width_and_height not found",
+        __FUNCTION__);
+  }
+}
+
+void AdrenoMemInfo::AlignCompressedRGB(int width, int height, int format, unsigned int *aligned_w,
+                                       unsigned int *aligned_h) {
+  if (LINK_adreno_compute_compressedfmt_aligned_width_and_height) {
+    int bytesPerPixel = 0;
+    int raster_mode = 0;          // Adreno unknown raster mode.
+    int padding_threshold = 512;  // Threshold for padding
+    // surfaces.
+
+    LINK_adreno_compute_compressedfmt_aligned_width_and_height(
+        width, height, format, 0, raster_mode, padding_threshold,
+        reinterpret_cast<int *>(aligned_w), reinterpret_cast<int *>(aligned_h), &bytesPerPixel);
+  } else {
+    ALOGW("%s: Warning!! compute_compressedfmt_aligned_width_and_height not found", __FUNCTION__);
+  }
+}
+
+bool AdrenoMemInfo::IsUBWCSupportedByGPU(int format) {
+  if (!gfx_ubwc_disable_ && LINK_adreno_isUBWCSupportedByGpu) {
+    ADRENOPIXELFORMAT gpu_format = GetGpuPixelFormat(format);
+    return LINK_adreno_isUBWCSupportedByGpu(gpu_format);
+  }
+
+  return false;
+}
+
+uint32_t AdrenoMemInfo::GetGpuPixelAlignment() {
+  if (LINK_adreno_get_gpu_pixel_alignment) {
+    return LINK_adreno_get_gpu_pixel_alignment();
+  }
+
+  return 1;
+}
+
+ADRENOPIXELFORMAT AdrenoMemInfo::GetGpuPixelFormat(int hal_format) {
+  switch (hal_format) {
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+      return ADRENO_PIXELFORMAT_R8G8B8A8;
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+      return ADRENO_PIXELFORMAT_R8G8B8X8;
+    case HAL_PIXEL_FORMAT_RGB_565:
+      return ADRENO_PIXELFORMAT_B5G6R5;
+    case HAL_PIXEL_FORMAT_BGR_565:
+      return ADRENO_PIXELFORMAT_R5G6B5;
+    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+      return ADRENO_PIXELFORMAT_NV12;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+      return ADRENO_PIXELFORMAT_NV12_EXT;
+    case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+      return ADRENO_PIXELFORMAT_TP10;
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+      return ADRENO_PIXELFORMAT_P010;
+    case HAL_PIXEL_FORMAT_RGBA_1010102:
+       return ADRENO_PIXELFORMAT_R10G10B10A2_UNORM;
+    case HAL_PIXEL_FORMAT_RGBX_1010102:
+       return ADRENO_PIXELFORMAT_R10G10B10X2_UNORM;
+    case HAL_PIXEL_FORMAT_ABGR_2101010:
+       return ADRENO_PIXELFORMAT_A2B10G10R10_UNORM;
+    default:
+      ALOGE("%s: No map for format: 0x%x", __FUNCTION__, hal_format);
+      break;
+  }
+
+  return ADRENO_PIXELFORMAT_UNKNOWN;
+}
+
+}  // namespace gralloc1
diff --git a/sdm845/libgralloc1/gr_adreno_info.h b/sdm845/libgralloc1/gr_adreno_info.h
new file mode 100644
index 0000000..75ba507
--- /dev/null
+++ b/sdm845/libgralloc1/gr_adreno_info.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2011-2017, 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 __GR_ADRENO_INFO_H__
+#define __GR_ADRENO_INFO_H__
+
+#include <media/msm_media_info.h>
+
+namespace gralloc1 {
+
+// Adreno Pixel Formats
+typedef enum {
+  ADRENO_PIXELFORMAT_UNKNOWN = 0,
+  ADRENO_PIXELFORMAT_R10G10B10A2_UNORM = 24,  // Vertex, Normalized GL_UNSIGNED_INT_10_10_10_2_OES
+  ADRENO_PIXELFORMAT_R8G8B8A8 = 28,
+  ADRENO_PIXELFORMAT_R8G8B8A8_SRGB = 29,
+  ADRENO_PIXELFORMAT_B5G6R5 = 85,
+  ADRENO_PIXELFORMAT_B5G5R5A1 = 86,
+  ADRENO_PIXELFORMAT_B8G8R8A8 = 90,
+  ADRENO_PIXELFORMAT_B8G8R8A8_SRGB = 91,
+  ADRENO_PIXELFORMAT_B8G8R8X8_SRGB = 93,
+  ADRENO_PIXELFORMAT_NV12 = 103,
+  ADRENO_PIXELFORMAT_P010 = 104,
+  ADRENO_PIXELFORMAT_YUY2 = 107,
+  ADRENO_PIXELFORMAT_B4G4R4A4 = 115,
+  ADRENO_PIXELFORMAT_NV12_EXT = 506,       // NV12 with non-std alignment and offsets
+  ADRENO_PIXELFORMAT_R8G8B8X8 = 507,       //  GL_RGB8 (Internal)
+  ADRENO_PIXELFORMAT_R8G8B8 = 508,         //  GL_RGB8
+  ADRENO_PIXELFORMAT_A1B5G5R5 = 519,       //  GL_RGB5_A1
+  ADRENO_PIXELFORMAT_R8G8B8X8_SRGB = 520,  //  GL_SRGB8
+  ADRENO_PIXELFORMAT_R8G8B8_SRGB = 521,    //  GL_SRGB8
+  ADRENO_PIXELFORMAT_A2B10G10R10_UNORM = 532,
+                                          // Vertex, Normalized GL_UNSIGNED_INT_10_10_10_2_OES
+  ADRENO_PIXELFORMAT_R10G10B10X2_UNORM = 537,
+                                          // Vertex, Normalized GL_UNSIGNED_INT_10_10_10_2_OES
+  ADRENO_PIXELFORMAT_R5G6B5 = 610,         //  RGBA version of B5G6R5
+  ADRENO_PIXELFORMAT_R5G5B5A1 = 611,       //  RGBA version of B5G5R5A1
+  ADRENO_PIXELFORMAT_R4G4B4A4 = 612,       //  RGBA version of B4G4R4A4
+  ADRENO_PIXELFORMAT_UYVY = 614,           //  YUV 4:2:2 packed progressive (1 plane)
+  ADRENO_PIXELFORMAT_NV21 = 619,
+  ADRENO_PIXELFORMAT_Y8U8V8A8 = 620,  // YUV 4:4:4 packed (1 plane)
+  ADRENO_PIXELFORMAT_Y8 = 625,        //  Single 8-bit luma only channel YUV format
+  ADRENO_PIXELFORMAT_TP10 = 648,      // YUV 4:2:0 planar 10 bits/comp (2 planes)
+} ADRENOPIXELFORMAT;
+
+class AdrenoMemInfo {
+ public:
+  bool Init();
+
+  /*
+   * Function to compute aligned width and aligned height based on
+   * width, height, format and usage flags.
+   *
+   * @return aligned width, aligned height
+   */
+  void GetAlignedWidthAndHeight(int width, int height, int format, int usage,
+                                unsigned int *aligned_w, unsigned int *aligned_h, bool ubwc_enabled,
+                                bool tile_enabled);
+
+  /*
+   * Function to compute the adreno aligned width and aligned height
+   * based on the width and format.
+   *
+   * @return aligned width, aligned height
+   */
+  void AlignUnCompressedRGB(int width, int height, int format, int tileEnabled,
+                            unsigned int *aligned_w, unsigned int *aligned_h);
+
+  /*
+   * Function to compute the adreno aligned width and aligned height
+   * based on the width and format.
+   *
+   * @return aligned width, aligned height
+   */
+  void AlignCompressedRGB(int width, int height, int format, unsigned int *aligned_w,
+                          unsigned int *aligned_h);
+
+  /*
+   * Function to compute the pixel alignment requirement.
+   *
+   * @return alignment
+   */
+  uint32_t GetGpuPixelAlignment();
+
+  /*
+   * Function to query whether GPU supports UBWC for given HAL format
+   * @return > 0 : supported
+   *           0 : not supported
+   */
+  bool IsUBWCSupportedByGPU(int format);
+
+  /*
+   * Function to get the corresponding Adreno format for given HAL format
+   */
+  ADRENOPIXELFORMAT GetGpuPixelFormat(int hal_format);
+
+  static AdrenoMemInfo *GetInstance();
+
+ private:
+  ~AdrenoMemInfo();
+  // link(s)to adreno surface padding library.
+  int (*LINK_adreno_compute_padding)(int width, int bpp, int surface_tile_height,
+                                     int screen_tile_height, int padding_threshold) = NULL;
+  void (*LINK_adreno_compute_aligned_width_and_height)(int width, int height, int bpp,
+                                                       int tile_mode, int raster_mode,
+                                                       int padding_threshold, int *aligned_w,
+                                                       int *aligned_h) = NULL;
+  void (*LINK_adreno_compute_fmt_aligned_width_and_height)(int width, int height, int plane_id,
+                                                           int format, int num_samples,
+                                                           int tile_mode, int raster_mode,
+                                                           int padding_threshold, int *aligned_w,
+                                                           int *aligned_h) = NULL;
+  void (*LINK_adreno_compute_compressedfmt_aligned_width_and_height)(
+      int width, int height, int format, int tile_mode, int raster_mode, int padding_threshold,
+      int *aligned_w, int *aligned_h, int *bpp) = NULL;
+  int (*LINK_adreno_isUBWCSupportedByGpu)(ADRENOPIXELFORMAT format) = NULL;
+  unsigned int (*LINK_adreno_get_gpu_pixel_alignment)() = NULL;
+
+  bool gfx_ubwc_disable_ = false;
+  bool map_fb_ = false;
+  void *libadreno_utils_ = NULL;
+
+  static AdrenoMemInfo *s_instance;
+};
+
+}  // namespace gralloc1
+
+#endif  // __GR_ADRENO_INFO_H__
diff --git a/sdm845/libgralloc1/gr_allocator.cpp b/sdm845/libgralloc1/gr_allocator.cpp
new file mode 100644
index 0000000..ee311f5
--- /dev/null
+++ b/sdm845/libgralloc1/gr_allocator.cpp
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2011-2017, 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/log.h>
+#include <algorithm>
+#include <vector>
+
+#include "gr_utils.h"
+#include "gr_allocator.h"
+#include "gralloc_priv.h"
+
+#include "qd_utils.h"
+
+#ifndef ION_FLAG_CP_PIXEL
+#define ION_FLAG_CP_PIXEL 0
+#endif
+
+#ifndef ION_FLAG_ALLOW_NON_CONTIG
+#define ION_FLAG_ALLOW_NON_CONTIG 0
+#endif
+
+#ifndef ION_FLAG_CP_CAMERA_PREVIEW
+#define ION_FLAG_CP_CAMERA_PREVIEW 0
+#endif
+
+#ifdef MASTER_SIDE_CP
+#define CP_HEAP_ID ION_SECURE_HEAP_ID
+#define SD_HEAP_ID ION_SECURE_DISPLAY_HEAP_ID
+#define ION_CP_FLAGS (ION_SECURE | ION_FLAG_CP_PIXEL)
+#define ION_SD_FLAGS (ION_SECURE | ION_FLAG_CP_SEC_DISPLAY)
+#define ION_SC_FLAGS (ION_SECURE | ION_FLAG_CP_CAMERA)
+#define ION_SC_PREVIEW_FLAGS (ION_SECURE | ION_FLAG_CP_CAMERA_PREVIEW)
+#else  // SLAVE_SIDE_CP
+#define CP_HEAP_ID ION_CP_MM_HEAP_ID
+#define SD_HEAP_ID CP_HEAP_ID
+#define ION_CP_FLAGS (ION_SECURE | ION_FLAG_ALLOW_NON_CONTIG)
+#define ION_SD_FLAGS ION_SECURE
+#define ION_SC_FLAGS ION_SECURE
+#define ION_SC_PREVIEW_FLAGS ION_SECURE
+#endif
+
+using std::vector;
+using std::shared_ptr;
+
+namespace gralloc1 {
+
+static BufferInfo GetBufferInfo(const BufferDescriptor &descriptor) {
+  return BufferInfo(descriptor.GetWidth(), descriptor.GetHeight(), descriptor.GetFormat(),
+                    descriptor.GetProducerUsage(), descriptor.GetConsumerUsage());
+}
+
+Allocator::Allocator() : ion_allocator_(NULL) {
+}
+
+bool Allocator::Init() {
+  ion_allocator_ = new IonAlloc();
+  if (!ion_allocator_->Init()) {
+    return false;
+  }
+
+  return true;
+}
+
+Allocator::~Allocator() {
+  if (ion_allocator_) {
+    delete ion_allocator_;
+  }
+}
+
+int Allocator::AllocateMem(AllocData *alloc_data, gralloc1_producer_usage_t prod_usage,
+                           gralloc1_consumer_usage_t cons_usage) {
+  int ret;
+  alloc_data->uncached = UseUncached(prod_usage, cons_usage);
+
+  // After this point we should have the right heap set, there is no fallback
+  GetIonHeapInfo(prod_usage, cons_usage, &alloc_data->heap_id, &alloc_data->alloc_type,
+                 &alloc_data->flags);
+
+  ret = ion_allocator_->AllocBuffer(alloc_data);
+  if (ret >= 0) {
+    alloc_data->alloc_type |= private_handle_t::PRIV_FLAGS_USES_ION;
+  } else {
+    ALOGE("%s: Failed to allocate buffer - heap: 0x%x flags: 0x%x", __FUNCTION__,
+          alloc_data->heap_id, alloc_data->flags);
+  }
+
+  return ret;
+}
+
+int Allocator::MapBuffer(void **base, unsigned int size, unsigned int offset, int fd) {
+  if (ion_allocator_) {
+    return ion_allocator_->MapBuffer(base, size, offset, fd);
+  }
+
+  return -EINVAL;
+}
+
+int Allocator::ImportBuffer(int fd) {
+  if (ion_allocator_) {
+    return ion_allocator_->ImportBuffer(fd);
+  }
+  return -EINVAL;
+}
+
+int Allocator::FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd,
+                          int handle) {
+  if (ion_allocator_) {
+    return ion_allocator_->FreeBuffer(base, size, offset, fd, handle);
+  }
+
+  return -EINVAL;
+}
+
+int Allocator::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op) {
+  if (ion_allocator_) {
+    return ion_allocator_->CleanBuffer(base, size, offset, handle, op);
+  }
+
+  return -EINVAL;
+}
+
+bool Allocator::CheckForBufferSharing(uint32_t num_descriptors,
+                                      const vector<shared_ptr<BufferDescriptor>>& descriptors,
+                                      ssize_t *max_index) {
+  unsigned int cur_heap_id = 0, prev_heap_id = 0;
+  unsigned int cur_alloc_type = 0, prev_alloc_type = 0;
+  unsigned int cur_ion_flags = 0, prev_ion_flags = 0;
+  bool cur_uncached = false, prev_uncached = false;
+  unsigned int alignedw, alignedh;
+  unsigned int max_size = 0;
+
+  *max_index = -1;
+  for (uint32_t i = 0; i < num_descriptors; i++) {
+    // Check Cached vs non-cached and all the ION flags
+    cur_uncached = UseUncached(descriptors[i]->GetProducerUsage(),
+                               descriptors[i]->GetConsumerUsage());
+    GetIonHeapInfo(descriptors[i]->GetProducerUsage(), descriptors[i]->GetConsumerUsage(),
+                   &cur_heap_id, &cur_alloc_type, &cur_ion_flags);
+
+    if (i > 0 && (cur_heap_id != prev_heap_id || cur_alloc_type != prev_alloc_type ||
+                  cur_ion_flags != prev_ion_flags)) {
+      return false;
+    }
+
+    // For same format type, find the descriptor with bigger size
+    GetAlignedWidthAndHeight(GetBufferInfo(*descriptors[i]), &alignedw, &alignedh);
+    unsigned int size = GetSize(GetBufferInfo(*descriptors[i]), alignedw, alignedh);
+    if (max_size < size) {
+      *max_index = INT(i);
+      max_size = size;
+    }
+
+    prev_heap_id = cur_heap_id;
+    prev_uncached = cur_uncached;
+    prev_ion_flags = cur_ion_flags;
+    prev_alloc_type = cur_alloc_type;
+  }
+
+  return true;
+}
+
+int Allocator::GetImplDefinedFormat(gralloc1_producer_usage_t prod_usage,
+                                    gralloc1_consumer_usage_t cons_usage, int format) {
+  int gr_format = format;
+
+  // If input format is HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED then based on
+  // the usage bits, gralloc assigns a format.
+  if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
+      format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+    if (prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_ALLOC_UBWC) {
+      gr_format = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+    } else if (cons_usage & GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER) {
+      gr_format = HAL_PIXEL_FORMAT_NV12_ENCODEABLE;  // NV12
+    } else if (cons_usage & GRALLOC1_CONSUMER_USAGE_CAMERA) {
+      if (prod_usage & GRALLOC1_PRODUCER_USAGE_CAMERA) {
+        // Assumed ZSL if both producer and consumer camera flags set
+        gr_format = HAL_PIXEL_FORMAT_NV21_ZSL;  // NV21
+      } else {
+        gr_format = HAL_PIXEL_FORMAT_YCrCb_420_SP;  // NV21
+      }
+    } else if (prod_usage & GRALLOC1_PRODUCER_USAGE_CAMERA) {
+      if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+        gr_format = HAL_PIXEL_FORMAT_NV21_ZSL;  // NV21
+      } else {
+        gr_format = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS;  // NV12 preview
+      }
+    } else if (cons_usage & GRALLOC1_CONSUMER_USAGE_HWCOMPOSER) {
+      // XXX: If we still haven't set a format, default to RGBA8888
+      gr_format = HAL_PIXEL_FORMAT_RGBA_8888;
+    } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+      // If no other usage flags are detected, default the
+      // flexible YUV format to NV21_ZSL
+      gr_format = HAL_PIXEL_FORMAT_NV21_ZSL;
+    }
+  }
+
+  return gr_format;
+}
+
+/* The default policy is to return cached buffers unless the client explicity
+ * sets the PRIVATE_UNCACHED flag or indicates that the buffer will be rarely
+ * read or written in software. */
+bool Allocator::UseUncached(gralloc1_producer_usage_t prod_usage,
+                            gralloc1_consumer_usage_t cons_usage) {
+  if ((prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_UNCACHED) ||
+      (prod_usage & GRALLOC1_PRODUCER_USAGE_PROTECTED)) {
+    return true;
+  }
+
+  // CPU read rarely
+  if ((prod_usage & GRALLOC1_PRODUCER_USAGE_CPU_READ) &&
+      !(prod_usage & GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN)) {
+    return true;
+  }
+
+  // CPU  write rarely
+  if ((prod_usage & GRALLOC1_PRODUCER_USAGE_CPU_WRITE) &&
+      !(prod_usage & GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN)) {
+    return true;
+  }
+
+  if ((prod_usage & GRALLOC1_PRODUCER_USAGE_SENSOR_DIRECT_DATA) ||
+      (cons_usage & GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER)) {
+    return true;
+  }
+
+  return false;
+}
+
+void Allocator::GetIonHeapInfo(gralloc1_producer_usage_t prod_usage,
+                               gralloc1_consumer_usage_t cons_usage, unsigned int *ion_heap_id,
+                               unsigned int *alloc_type, unsigned int *ion_flags) {
+  unsigned int heap_id = 0;
+  unsigned int type = 0;
+  uint32_t flags = 0;
+  if (prod_usage & GRALLOC1_PRODUCER_USAGE_PROTECTED) {
+    if (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY) {
+      heap_id = ION_HEAP(SD_HEAP_ID);
+      /*
+       * There is currently no flag in ION for Secure Display
+       * VM. Please add it to the define once available.
+       */
+      flags |= UINT(ION_SD_FLAGS);
+    } else if (prod_usage & GRALLOC1_PRODUCER_USAGE_CAMERA) {
+      heap_id = ION_HEAP(SD_HEAP_ID);
+      if (cons_usage & GRALLOC1_CONSUMER_USAGE_HWCOMPOSER) {
+        flags |= UINT(ION_SC_PREVIEW_FLAGS);
+      } else {
+        flags |= UINT(ION_SC_FLAGS);
+      }
+    } else {
+      heap_id = ION_HEAP(CP_HEAP_ID);
+      flags |= UINT(ION_CP_FLAGS);
+    }
+  } else if (prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_MM_HEAP) {
+    // MM Heap is exclusively a secure heap.
+    // If it is used for non secure cases, fallback to IOMMU heap
+    ALOGW("MM_HEAP cannot be used as an insecure heap. Using system heap instead!!");
+    heap_id |= ION_HEAP(ION_SYSTEM_HEAP_ID);
+  }
+
+  if (prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_CAMERA_HEAP) {
+    heap_id |= ION_HEAP(ION_CAMERA_HEAP_ID);
+  }
+
+  if (prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_ADSP_HEAP ||
+      prod_usage & GRALLOC1_PRODUCER_USAGE_SENSOR_DIRECT_DATA) {
+    heap_id |= ION_HEAP(ION_ADSP_HEAP_ID);
+  }
+
+  if (flags & UINT(ION_SECURE)) {
+    type |= private_handle_t::PRIV_FLAGS_SECURE_BUFFER;
+  }
+
+  // if no ion heap flags are set, default to system heap
+  if (!heap_id) {
+    heap_id = ION_HEAP(ION_SYSTEM_HEAP_ID);
+  }
+
+  *alloc_type = type;
+  *ion_flags = flags;
+  *ion_heap_id = heap_id;
+
+  return;
+}
+}  // namespace gralloc1
diff --git a/sdm845/libgralloc1/gr_allocator.h b/sdm845/libgralloc1/gr_allocator.h
new file mode 100644
index 0000000..d57f50e
--- /dev/null
+++ b/sdm845/libgralloc1/gr_allocator.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011-2017, 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 __GR_ALLOCATOR_H__
+#define __GR_ALLOCATOR_H__
+
+#ifdef MASTER_SIDE_CP
+#define SECURE_ALIGN SZ_4K
+#else
+#define SECURE_ALIGN SZ_1M
+#endif
+
+#include <vector>
+
+#include "gralloc_priv.h"
+#include "gr_buf_descriptor.h"
+#include "gr_ion_alloc.h"
+
+namespace gralloc1 {
+
+class Allocator {
+ public:
+  Allocator();
+  ~Allocator();
+  bool Init();
+  int MapBuffer(void **base, unsigned int size, unsigned int offset, int fd);
+  int ImportBuffer(int fd);
+  int FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd, int handle);
+  int CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op);
+  int AllocateMem(AllocData *data, gralloc1_producer_usage_t prod_usage,
+                  gralloc1_consumer_usage_t cons_usage);
+  // @return : index of the descriptor with maximum buffer size req
+  bool CheckForBufferSharing(uint32_t num_descriptors,
+                             const std::vector<std::shared_ptr<BufferDescriptor>>& descriptors,
+                             ssize_t *max_index);
+  int GetImplDefinedFormat(gralloc1_producer_usage_t prod_usage,
+                           gralloc1_consumer_usage_t cons_usage, int format);
+  bool UseUncached(gralloc1_producer_usage_t prod_usage, gralloc1_consumer_usage_t cons_usage);
+
+ private:
+  void GetIonHeapInfo(gralloc1_producer_usage_t prod_usage, gralloc1_consumer_usage_t cons_usage,
+                      unsigned int *ion_heap_id, unsigned int *alloc_type, unsigned int *ion_flags);
+
+  IonAlloc *ion_allocator_ = NULL;
+};
+
+}  // namespace gralloc1
+
+#endif  // __GR_ALLOCATOR_H__
diff --git a/sdm845/libgralloc1/gr_buf_descriptor.h b/sdm845/libgralloc1/gr_buf_descriptor.h
new file mode 100644
index 0000000..c909fa4
--- /dev/null
+++ b/sdm845/libgralloc1/gr_buf_descriptor.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016-2017, 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 __GR_BUF_DESCRIPTOR_H__
+#define __GR_BUF_DESCRIPTOR_H__
+
+#include <hardware/gralloc1.h>
+#include <atomic>
+
+namespace gralloc1 {
+class BufferDescriptor {
+ public:
+  BufferDescriptor() : id_(next_id_++) {}
+
+  BufferDescriptor(int w, int h, int f)
+      : width_(w),
+        height_(h),
+        format_(f),
+        producer_usage_(GRALLOC1_PRODUCER_USAGE_NONE),
+        consumer_usage_(GRALLOC1_CONSUMER_USAGE_NONE),
+        id_(next_id_++) {}
+
+  BufferDescriptor(int w, int h, int f, gralloc1_producer_usage_t prod_usage,
+                   gralloc1_consumer_usage_t cons_usage)
+      : width_(w),
+        height_(h),
+        format_(f),
+        producer_usage_(prod_usage),
+        consumer_usage_(cons_usage),
+        id_(next_id_++) {}
+
+  void SetConsumerUsage(gralloc1_consumer_usage_t usage) { consumer_usage_ = usage; }
+
+  void SetProducerUsage(gralloc1_producer_usage_t usage) { producer_usage_ = usage; }
+
+  void SetDimensions(int w, int h) {
+    width_ = w;
+    height_ = h;
+  }
+
+  void SetColorFormat(int format) { format_ = format; }
+
+  void SetLayerCount(uint32_t layer_count) { layer_count_ = layer_count; }
+
+  gralloc1_consumer_usage_t GetConsumerUsage() const { return consumer_usage_; }
+
+  gralloc1_producer_usage_t GetProducerUsage() const { return producer_usage_; }
+
+  int GetWidth() const { return width_; }
+
+  int GetHeight() const { return height_; }
+
+  int GetFormat() const { return format_; }
+
+  uint32_t GetLayerCount() const { return layer_count_; }
+
+  gralloc1_buffer_descriptor_t GetId() const { return id_; }
+
+ private:
+  int width_ = -1;
+  int height_ = -1;
+  int format_ = -1;
+  uint32_t layer_count_ = 1;
+  gralloc1_producer_usage_t producer_usage_ = GRALLOC1_PRODUCER_USAGE_NONE;
+  gralloc1_consumer_usage_t consumer_usage_ = GRALLOC1_CONSUMER_USAGE_NONE;
+  const gralloc1_buffer_descriptor_t id_;
+  static std::atomic<gralloc1_buffer_descriptor_t> next_id_;
+};
+};  // namespace gralloc1
+#endif  // __GR_BUF_DESCRIPTOR_H__
diff --git a/sdm845/libgralloc1/gr_buf_mgr.cpp b/sdm845/libgralloc1/gr_buf_mgr.cpp
new file mode 100644
index 0000000..7e0ba14
--- /dev/null
+++ b/sdm845/libgralloc1/gr_buf_mgr.cpp
@@ -0,0 +1,886 @@
+/*
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define DEBUG 0
+
+#include <iomanip>
+#include <utility>
+#include <vector>
+#include <sstream>
+
+#include "qd_utils.h"
+#include "gr_priv_handle.h"
+#include "gr_buf_descriptor.h"
+#include "gr_utils.h"
+#include "gr_buf_mgr.h"
+#include "qdMetaData.h"
+
+namespace gralloc1 {
+std::atomic<gralloc1_buffer_descriptor_t> BufferDescriptor::next_id_(1);
+
+static BufferInfo GetBufferInfo(const BufferDescriptor &descriptor) {
+  return BufferInfo(descriptor.GetWidth(), descriptor.GetHeight(), descriptor.GetFormat(),
+                    descriptor.GetProducerUsage(), descriptor.GetConsumerUsage());
+}
+
+BufferManager::BufferManager() : next_id_(0) {
+  char property[PROPERTY_VALUE_MAX];
+
+  // Map framebuffer memory
+  if ((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
+      (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
+       (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)))) {
+    map_fb_mem_ = true;
+  }
+
+  // Enable UBWC for framebuffer
+  if ((property_get("debug.gralloc.enable_fb_ubwc", property, NULL) > 0) &&
+      (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
+       (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)))) {
+    ubwc_for_fb_ = true;
+  }
+
+  handles_map_.clear();
+  allocator_ = new Allocator();
+  allocator_->Init();
+}
+
+
+gralloc1_error_t BufferManager::CreateBufferDescriptor(
+    gralloc1_buffer_descriptor_t *descriptor_id) {
+  std::lock_guard<std::mutex> lock(descriptor_lock_);
+  auto descriptor = std::make_shared<BufferDescriptor>();
+  descriptors_map_.emplace(descriptor->GetId(), descriptor);
+  *descriptor_id = descriptor->GetId();
+  return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t BufferManager::DestroyBufferDescriptor(
+    gralloc1_buffer_descriptor_t descriptor_id) {
+  std::lock_guard<std::mutex> lock(descriptor_lock_);
+  const auto descriptor = descriptors_map_.find(descriptor_id);
+  if (descriptor == descriptors_map_.end()) {
+    return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+  }
+  descriptors_map_.erase(descriptor);
+  return GRALLOC1_ERROR_NONE;
+}
+
+BufferManager::~BufferManager() {
+  if (allocator_) {
+    delete allocator_;
+  }
+}
+
+gralloc1_error_t BufferManager::AllocateBuffers(uint32_t num_descriptors,
+                                                const gralloc1_buffer_descriptor_t *descriptor_ids,
+                                                buffer_handle_t *out_buffers) {
+  bool shared = true;
+  gralloc1_error_t status = GRALLOC1_ERROR_NONE;
+
+  // since GRALLOC1_CAPABILITY_TEST_ALLOCATE capability is supported
+  // client can ask to test the allocation by passing NULL out_buffers
+  bool test_allocate = !out_buffers;
+
+  // Validate descriptors
+  std::lock_guard<std::mutex> descriptor_lock(descriptor_lock_);
+  std::vector<std::shared_ptr<BufferDescriptor>> descriptors;
+  for (uint32_t i = 0; i < num_descriptors; i++) {
+    const auto map_descriptor = descriptors_map_.find(descriptor_ids[i]);
+    if (map_descriptor == descriptors_map_.end()) {
+      return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+    } else {
+      descriptors.push_back(map_descriptor->second);
+    }
+  }
+
+  //  Resolve implementation defined formats
+  for (auto &descriptor : descriptors) {
+    descriptor->SetColorFormat(allocator_->GetImplDefinedFormat(descriptor->GetProducerUsage(),
+                                                                descriptor->GetConsumerUsage(),
+                                                                descriptor->GetFormat()));
+  }
+
+  // Check if input descriptors can be supported AND
+  // Find out if a single buffer can be shared for all the given input descriptors
+  uint32_t i = 0;
+  ssize_t max_buf_index = -1;
+  shared = allocator_->CheckForBufferSharing(num_descriptors, descriptors, &max_buf_index);
+
+  if (test_allocate) {
+    status = shared ? GRALLOC1_ERROR_NOT_SHARED : status;
+    return status;
+  }
+
+  std::lock_guard<std::mutex> buffer_lock(buffer_lock_);
+  if (shared && (max_buf_index >= 0)) {
+    // Allocate one and duplicate/copy the handles for each descriptor
+    if (AllocateBuffer(*descriptors[UINT(max_buf_index)], &out_buffers[max_buf_index])) {
+      return GRALLOC1_ERROR_NO_RESOURCES;
+    }
+
+    for (i = 0; i < num_descriptors; i++) {
+      // Create new handle for a given descriptor.
+      // Current assumption is even MetaData memory would be same
+      // Need to revisit if there is a need for own metadata memory
+      if (i != UINT(max_buf_index)) {
+        CreateSharedHandle(out_buffers[max_buf_index], *descriptors[i], &out_buffers[i]);
+      }
+    }
+  } else {
+    // Buffer sharing is not feasible.
+    // Allocate separate buffer for each descriptor
+    for (i = 0; i < num_descriptors; i++) {
+      if (AllocateBuffer(*descriptors[i], &out_buffers[i])) {
+        return GRALLOC1_ERROR_NO_RESOURCES;
+      }
+    }
+  }
+
+  // Allocation is successful. If backstore is not shared inform the client.
+  if (!shared) {
+    return GRALLOC1_ERROR_NOT_SHARED;
+  }
+
+  return status;
+}
+
+void BufferManager::CreateSharedHandle(buffer_handle_t inbuffer, const BufferDescriptor &descriptor,
+                                       buffer_handle_t *outbuffer) {
+  // TODO(user): This path is not verified
+  private_handle_t const *input = reinterpret_cast<private_handle_t const *>(inbuffer);
+
+  // Get Buffer attributes or dimension
+  unsigned int alignedw = 0, alignedh = 0;
+  BufferInfo info = GetBufferInfo(descriptor);
+
+  GetAlignedWidthAndHeight(info, &alignedw, &alignedh);
+
+  // create new handle from input reference handle and given descriptor
+  int flags = GetHandleFlags(descriptor.GetFormat(), descriptor.GetProducerUsage(),
+                             descriptor.GetConsumerUsage());
+  int buffer_type = GetBufferType(descriptor.GetFormat());
+
+  // Duplicate the fds
+  // TODO(user): Not sure what to do for fb_id. Use duped fd and new dimensions?
+  private_handle_t *out_hnd = new private_handle_t(dup(input->fd),
+                                                   dup(input->fd_metadata),
+                                                   flags,
+                                                   INT(alignedw),
+                                                   INT(alignedh),
+                                                   descriptor.GetWidth(),
+                                                   descriptor.GetHeight(),
+                                                   descriptor.GetFormat(),
+                                                   buffer_type,
+                                                   input->size,
+                                                   descriptor.GetProducerUsage(),
+                                                   descriptor.GetConsumerUsage());
+  out_hnd->id = ++next_id_;
+  // TODO(user): Base address of shared handle and ion handles
+  RegisterHandleLocked(out_hnd, -1, -1);
+  *outbuffer = out_hnd;
+}
+
+gralloc1_error_t BufferManager::FreeBuffer(std::shared_ptr<Buffer> buf) {
+  auto hnd = buf->handle;
+  ALOGD_IF(DEBUG, "FreeBuffer handle:%p id: %" PRIu64, hnd, hnd->id);
+  if (allocator_->FreeBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
+                             hnd->fd, buf->ion_handle_main) != 0) {
+    return GRALLOC1_ERROR_BAD_HANDLE;
+  }
+
+  unsigned int meta_size = ALIGN((unsigned int)sizeof(MetaData_t), PAGE_SIZE);
+  if (allocator_->FreeBuffer(reinterpret_cast<void *>(hnd->base_metadata), meta_size,
+                             hnd->offset_metadata, hnd->fd_metadata, buf->ion_handle_meta) != 0) {
+    return GRALLOC1_ERROR_BAD_HANDLE;
+  }
+
+  private_handle_t * handle = const_cast<private_handle_t *>(hnd);
+  handle->fd = -1;
+  handle->fd_metadata = -1;
+  delete handle;
+  return GRALLOC1_ERROR_NONE;
+}
+
+void BufferManager::RegisterHandleLocked(const private_handle_t *hnd,
+                                         int ion_handle,
+                                         int ion_handle_meta) {
+  auto buffer = std::make_shared<Buffer>(hnd, ion_handle, ion_handle_meta);
+  handles_map_.emplace(std::make_pair(hnd, buffer));
+}
+
+gralloc1_error_t BufferManager::ImportHandleLocked(private_handle_t *hnd) {
+  ALOGD_IF(DEBUG, "Importing handle:%p id: %" PRIu64, hnd, hnd->id);
+  int ion_handle = allocator_->ImportBuffer(hnd->fd);
+  if (ion_handle < 0) {
+    ALOGE("Failed to import ion buffer: hnd: %p, fd:%d, id:%" PRIu64, hnd, hnd->fd, hnd->id);
+    return GRALLOC1_ERROR_BAD_HANDLE;
+  }
+  int ion_handle_meta = allocator_->ImportBuffer(hnd->fd_metadata);
+  if (ion_handle_meta < 0) {
+    ALOGE("Failed to import ion metadata buffer: hnd: %p, fd:%d, id:%" PRIu64, hnd,
+          hnd->fd, hnd->id);
+    return GRALLOC1_ERROR_BAD_HANDLE;
+  }
+  // Set base pointers to NULL since the data here was received over binder
+  hnd->base = 0;
+  hnd->base_metadata = 0;
+  RegisterHandleLocked(hnd, ion_handle, ion_handle_meta);
+  return GRALLOC1_ERROR_NONE;
+}
+
+std::shared_ptr<BufferManager::Buffer>
+BufferManager::GetBufferFromHandleLocked(const private_handle_t *hnd) {
+  auto it = handles_map_.find(hnd);
+  if (it != handles_map_.end()) {
+    return it->second;
+  } else {
+    return nullptr;
+  }
+}
+
+gralloc1_error_t BufferManager::MapBuffer(private_handle_t const *handle) {
+  private_handle_t *hnd = const_cast<private_handle_t *>(handle);
+  ALOGD_IF(DEBUG, "Map buffer handle:%p id: %" PRIu64, hnd, hnd->id);
+
+  hnd->base = 0;
+  hnd->base_metadata = 0;
+
+  if (allocator_->MapBuffer(reinterpret_cast<void **>(&hnd->base), hnd->size, hnd->offset,
+                            hnd->fd) != 0) {
+    return GRALLOC1_ERROR_BAD_HANDLE;
+  }
+
+  unsigned int size = ALIGN((unsigned int)sizeof(MetaData_t), getpagesize());
+  if (allocator_->MapBuffer(reinterpret_cast<void **>(&hnd->base_metadata), size,
+                            hnd->offset_metadata, hnd->fd_metadata) != 0) {
+    return GRALLOC1_ERROR_BAD_HANDLE;
+  }
+
+  return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t BufferManager::RetainBuffer(private_handle_t const *hnd) {
+  if (hnd->flags & private_handle_t::PRIV_FLAGS_CLIENT_ALLOCATED) {
+    return GRALLOC1_ERROR_NONE;
+  }
+
+  ALOGD_IF(DEBUG, "Retain buffer handle:%p id: %" PRIu64, hnd, hnd->id);
+  gralloc1_error_t err = GRALLOC1_ERROR_NONE;
+  std::lock_guard<std::mutex> lock(buffer_lock_);
+  auto buf = GetBufferFromHandleLocked(hnd);
+  if (buf != nullptr) {
+    buf->IncRef();
+  } else {
+    private_handle_t *handle = const_cast<private_handle_t *>(hnd);
+    err = ImportHandleLocked(handle);
+    if (err == GRALLOC1_ERROR_NONE) {
+      // TODO(user): See bug 35955598
+      if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+        return GRALLOC1_ERROR_NONE;  // Don't map secure buffer
+      }
+      err = MapBuffer(hnd);
+    }
+  }
+  return err;
+}
+
+gralloc1_error_t BufferManager::ReleaseBuffer(private_handle_t const *hnd) {
+  if (hnd->flags & private_handle_t::PRIV_FLAGS_CLIENT_ALLOCATED) {
+    return GRALLOC1_ERROR_NONE;
+  }
+
+  ALOGD_IF(DEBUG, "Release buffer handle:%p id: %" PRIu64, hnd, hnd->id);
+  std::lock_guard<std::mutex> lock(buffer_lock_);
+  auto buf = GetBufferFromHandleLocked(hnd);
+  if (buf == nullptr) {
+    ALOGE("Could not find handle: %p id: %" PRIu64, hnd, hnd->id);
+    return GRALLOC1_ERROR_BAD_HANDLE;
+  } else {
+    if (buf->DecRef()) {
+      handles_map_.erase(hnd);
+      // Unmap, close ion handle and close fd
+      FreeBuffer(buf);
+    }
+  }
+  return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t BufferManager::LockBuffer(const private_handle_t *hnd,
+                                           gralloc1_producer_usage_t prod_usage,
+                                           gralloc1_consumer_usage_t cons_usage) {
+  std::lock_guard<std::mutex> lock(buffer_lock_);
+  gralloc1_error_t err = GRALLOC1_ERROR_NONE;
+  ALOGD_IF(DEBUG, "LockBuffer buffer handle:%p id: %" PRIu64, hnd, hnd->id);
+
+  // If buffer is not meant for CPU return err
+  if (!CpuCanAccess(prod_usage, cons_usage)) {
+    return GRALLOC1_ERROR_BAD_VALUE;
+  }
+
+  auto buf = GetBufferFromHandleLocked(hnd);
+  if (buf == nullptr) {
+    return GRALLOC1_ERROR_BAD_HANDLE;
+  }
+
+  if (hnd->base == 0) {
+    // we need to map for real
+    err = MapBuffer(hnd);
+  }
+
+  // Invalidate if CPU reads in software and there are non-CPU
+  // writers. No need to do this for the metadata buffer as it is
+  // only read/written in software.
+
+  // todo use handle here
+  if (!err && (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) &&
+      (hnd->flags & private_handle_t::PRIV_FLAGS_CACHED)) {
+    if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
+                                buf->ion_handle_main, CACHE_INVALIDATE)) {
+      return GRALLOC1_ERROR_BAD_HANDLE;
+    }
+  }
+
+  // Mark the buffer to be flushed after CPU write.
+  if (!err && CpuCanWrite(prod_usage)) {
+    private_handle_t *handle = const_cast<private_handle_t *>(hnd);
+    handle->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
+  }
+
+  return err;
+}
+
+gralloc1_error_t BufferManager::UnlockBuffer(const private_handle_t *handle) {
+  std::lock_guard<std::mutex> lock(buffer_lock_);
+  gralloc1_error_t status = GRALLOC1_ERROR_NONE;
+
+  private_handle_t *hnd = const_cast<private_handle_t *>(handle);
+  auto buf = GetBufferFromHandleLocked(hnd);
+  if (buf == nullptr) {
+    return GRALLOC1_ERROR_BAD_HANDLE;
+  }
+
+  if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
+    if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
+                                buf->ion_handle_main, CACHE_CLEAN) != 0) {
+      status = GRALLOC1_ERROR_BAD_HANDLE;
+    }
+    hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
+  }
+
+  return status;
+}
+
+uint32_t BufferManager::GetDataAlignment(int format, gralloc1_producer_usage_t prod_usage,
+                                    gralloc1_consumer_usage_t cons_usage) {
+  uint32_t align = UINT(getpagesize());
+  if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
+    align = 8192;
+  }
+
+  if (prod_usage & GRALLOC1_PRODUCER_USAGE_PROTECTED) {
+    if ((prod_usage & GRALLOC1_PRODUCER_USAGE_CAMERA) ||
+        (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY)) {
+      // The alignment here reflects qsee mmu V7L/V8L requirement
+      align = SZ_2M;
+    } else {
+      align = SECURE_ALIGN;
+    }
+  }
+
+  return align;
+}
+
+int BufferManager::GetHandleFlags(int format, gralloc1_producer_usage_t prod_usage,
+                                  gralloc1_consumer_usage_t cons_usage) {
+  int flags = 0;
+  if (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_EXTERNAL_ONLY) {
+    flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
+  }
+
+  if (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_INTERNAL_ONLY) {
+    flags |= private_handle_t::PRIV_FLAGS_INTERNAL_ONLY;
+  }
+
+  if (cons_usage & GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER) {
+    flags |= private_handle_t::PRIV_FLAGS_VIDEO_ENCODER;
+  }
+
+  if (prod_usage & GRALLOC1_PRODUCER_USAGE_CAMERA) {
+    flags |= private_handle_t::PRIV_FLAGS_CAMERA_WRITE;
+  }
+
+  if (prod_usage & GRALLOC1_CONSUMER_USAGE_CAMERA) {
+    flags |= private_handle_t::PRIV_FLAGS_CAMERA_READ;
+  }
+
+  if (cons_usage & GRALLOC1_CONSUMER_USAGE_HWCOMPOSER) {
+    flags |= private_handle_t::PRIV_FLAGS_HW_COMPOSER;
+  }
+
+  if (prod_usage & GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE) {
+    flags |= private_handle_t::PRIV_FLAGS_HW_TEXTURE;
+  }
+
+  if (prod_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY) {
+    flags |= private_handle_t::PRIV_FLAGS_SECURE_DISPLAY;
+  }
+
+  if (IsUBwcEnabled(format, prod_usage, cons_usage)) {
+    flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+  }
+
+  if (prod_usage & (GRALLOC1_PRODUCER_USAGE_CPU_READ | GRALLOC1_PRODUCER_USAGE_CPU_WRITE)) {
+    flags |= private_handle_t::PRIV_FLAGS_CPU_RENDERED;
+  }
+
+  // TODO(user): is this correct???
+  if ((cons_usage &
+       (GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER | GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET)) ||
+      (prod_usage & (GRALLOC1_PRODUCER_USAGE_CAMERA | GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET))) {
+    flags |= private_handle_t::PRIV_FLAGS_NON_CPU_WRITER;
+  }
+
+  if (cons_usage & GRALLOC1_CONSUMER_USAGE_HWCOMPOSER) {
+    flags |= private_handle_t::PRIV_FLAGS_DISP_CONSUMER;
+  }
+
+  if (!allocator_->UseUncached(prod_usage, cons_usage)) {
+    flags |= private_handle_t::PRIV_FLAGS_CACHED;
+  }
+
+  return flags;
+}
+
+int BufferManager::GetBufferType(int inputFormat) {
+  int buffer_type = BUFFER_TYPE_VIDEO;
+  if (IsUncompressedRGBFormat(inputFormat)) {
+    // RGB formats
+    buffer_type = BUFFER_TYPE_UI;
+  }
+
+  return buffer_type;
+}
+
+int BufferManager::AllocateBuffer(const BufferDescriptor &descriptor, buffer_handle_t *handle,
+                                  unsigned int bufferSize) {
+  if (!handle)
+    return -EINVAL;
+
+  int format = descriptor.GetFormat();
+  gralloc1_producer_usage_t prod_usage = descriptor.GetProducerUsage();
+  gralloc1_consumer_usage_t cons_usage = descriptor.GetConsumerUsage();
+  uint32_t layer_count = descriptor.GetLayerCount();
+
+  // Get implementation defined format
+  int gralloc_format = allocator_->GetImplDefinedFormat(prod_usage, cons_usage, format);
+
+  unsigned int size;
+  unsigned int alignedw, alignedh;
+  int buffer_type = GetBufferType(gralloc_format);
+  BufferInfo info = GetBufferInfo(descriptor);
+  GetBufferSizeAndDimensions(info, &size, &alignedw, &alignedh);
+  size = (bufferSize >= size) ? bufferSize : size;
+  size = size * layer_count;
+
+  int err = 0;
+  int flags = 0;
+  auto page_size = UINT(getpagesize());
+  AllocData data;
+  data.align = GetDataAlignment(format, prod_usage, cons_usage);
+  data.size = ALIGN(size, data.align);
+  data.handle = (uintptr_t) handle;
+  data.uncached = allocator_->UseUncached(prod_usage, cons_usage);
+
+  // Allocate buffer memory
+  err = allocator_->AllocateMem(&data, prod_usage, cons_usage);
+  if (err) {
+    ALOGE("gralloc failed to allocate err=%s", strerror(-err));
+    return err;
+  }
+
+  // Allocate memory for MetaData
+  AllocData e_data;
+  e_data.size = ALIGN(UINT(sizeof(MetaData_t)), page_size);
+  e_data.handle = data.handle;
+  e_data.align = page_size;
+
+  err =
+      allocator_->AllocateMem(&e_data, GRALLOC1_PRODUCER_USAGE_NONE, GRALLOC1_CONSUMER_USAGE_NONE);
+  if (err) {
+    ALOGE("gralloc failed to allocate metadata error=%s", strerror(-err));
+    return err;
+  }
+
+  flags = GetHandleFlags(format, prod_usage, cons_usage);
+  flags |= data.alloc_type;
+
+  // Create handle
+  private_handle_t *hnd = new private_handle_t(data.fd,
+                                               e_data.fd,
+                                               flags,
+                                               INT(alignedw),
+                                               INT(alignedh),
+                                               descriptor.GetWidth(),
+                                               descriptor.GetHeight(),
+                                               format,
+                                               buffer_type,
+                                               size,
+                                               prod_usage,
+                                               cons_usage);
+
+  hnd->id = ++next_id_;
+  hnd->base = 0;
+  hnd->base_metadata = 0;
+  hnd->layer_count = layer_count;
+
+  ColorSpace_t colorSpace = ITU_R_601;
+  setMetaData(hnd, UPDATE_COLOR_SPACE, reinterpret_cast<void *>(&colorSpace));
+  *handle = hnd;
+  RegisterHandleLocked(hnd, data.ion_handle, e_data.ion_handle);
+  ALOGD_IF(DEBUG, "Allocated buffer handle: %p id: %" PRIu64, hnd, hnd->id);
+  if (DEBUG) {
+    private_handle_t::Dump(hnd);
+  }
+  return err;
+}
+
+gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
+  switch (operation) {
+    case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: {
+      int fd = va_arg(args, int);
+      unsigned int size = va_arg(args, unsigned int);
+      unsigned int offset = va_arg(args, unsigned int);
+      void *base = va_arg(args, void *);
+      int width = va_arg(args, int);
+      int height = va_arg(args, int);
+      int format = va_arg(args, int);
+
+      native_handle_t **handle = va_arg(args, native_handle_t **);
+      private_handle_t *hnd = reinterpret_cast<private_handle_t *>(
+          native_handle_create(private_handle_t::kNumFds, private_handle_t::NumInts()));
+      if (hnd) {
+        unsigned int alignedw = 0, alignedh = 0;
+        hnd->magic = private_handle_t::kMagic;
+        hnd->fd = fd;
+        hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
+        hnd->size = size;
+        hnd->offset = offset;
+        hnd->base = uint64_t(base) + offset;
+        hnd->gpuaddr = 0;
+        BufferInfo info(width, height, format);
+        GetAlignedWidthAndHeight(info, &alignedw, &alignedh);
+        hnd->unaligned_width = width;
+        hnd->unaligned_height = height;
+        hnd->width = INT(alignedw);
+        hnd->height = INT(alignedh);
+        hnd->format = format;
+        *handle = reinterpret_cast<native_handle_t *>(hnd);
+      }
+    } break;
+
+    case GRALLOC_MODULE_PERFORM_GET_STRIDE: {
+      int width = va_arg(args, int);
+      int format = va_arg(args, int);
+      int *stride = va_arg(args, int *);
+      unsigned int alignedw = 0, alignedh = 0;
+      BufferInfo info(width, width, format);
+      GetAlignedWidthAndHeight(info, &alignedw, &alignedh);
+      *stride = INT(alignedw);
+    } break;
+
+    case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE: {
+      private_handle_t *hnd = va_arg(args, private_handle_t *);
+      int *stride = va_arg(args, int *);
+      if (private_handle_t::validate(hnd) != 0) {
+        return GRALLOC1_ERROR_BAD_HANDLE;
+      }
+
+      BufferDim_t buffer_dim;
+      if (getMetaData(hnd, GET_BUFFER_GEOMETRY, &buffer_dim) == 0) {
+        *stride = buffer_dim.sliceWidth;
+      } else {
+        *stride = hnd->width;
+      }
+    } break;
+
+    // TODO(user) : this alone should be sufficient, ask gfx to get rid of above
+    case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE: {
+      private_handle_t *hnd = va_arg(args, private_handle_t *);
+      int *stride = va_arg(args, int *);
+      int *height = va_arg(args, int *);
+      if (private_handle_t::validate(hnd) != 0) {
+        return GRALLOC1_ERROR_BAD_HANDLE;
+      }
+
+      BufferDim_t buffer_dim;
+      if (getMetaData(hnd, GET_BUFFER_GEOMETRY, &buffer_dim) == 0) {
+        *stride = buffer_dim.sliceWidth;
+        *height = buffer_dim.sliceHeight;
+      } else {
+        *stride = hnd->width;
+        *height = hnd->height;
+      }
+    } break;
+
+    case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES: {
+      // TODO(user): Usage is split now. take care of it from Gfx client.
+      // see if we can directly expect descriptor from gfx client.
+      int width = va_arg(args, int);
+      int height = va_arg(args, int);
+      int format = va_arg(args, int);
+      uint64_t producer_usage = va_arg(args, uint64_t);
+      uint64_t consumer_usage = va_arg(args, uint64_t);
+      gralloc1_producer_usage_t prod_usage = static_cast<gralloc1_producer_usage_t>(producer_usage);
+      gralloc1_consumer_usage_t cons_usage = static_cast<gralloc1_consumer_usage_t>(consumer_usage);
+
+      int *aligned_width = va_arg(args, int *);
+      int *aligned_height = va_arg(args, int *);
+      int *tile_enabled = va_arg(args, int *);
+      unsigned int alignedw, alignedh;
+      BufferInfo info(width, height, format, prod_usage, cons_usage);
+      *tile_enabled = IsUBwcEnabled(format, prod_usage, cons_usage);
+      GetAlignedWidthAndHeight(info, &alignedw, &alignedh);
+      *aligned_width = INT(alignedw);
+      *aligned_height = INT(alignedh);
+    } break;
+
+    case GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE: {
+      private_handle_t *hnd = va_arg(args, private_handle_t *);
+      int *color_space = va_arg(args, int *);
+      if (private_handle_t::validate(hnd) != 0) {
+        return GRALLOC1_ERROR_BAD_HANDLE;
+      }
+      *color_space = 0;
+#ifdef USE_COLOR_METADATA
+      ColorMetaData color_metadata;
+      if (getMetaData(hnd, GET_COLOR_METADATA, &color_metadata) == 0) {
+        switch (color_metadata.colorPrimaries) {
+          case ColorPrimaries_BT709_5:
+            *color_space = HAL_CSC_ITU_R_709;
+            break;
+          case ColorPrimaries_BT601_6_525:
+            *color_space = ((color_metadata.range) ? HAL_CSC_ITU_R_601_FR : HAL_CSC_ITU_R_601);
+            break;
+          case ColorPrimaries_BT2020:
+            *color_space = (color_metadata.range) ? HAL_CSC_ITU_R_2020_FR : HAL_CSC_ITU_R_2020;
+            break;
+          default:
+            ALOGE("Unknown Color Space = %d", color_metadata.colorPrimaries);
+            break;
+        }
+        break;
+      }
+      if (getMetaData(hnd, GET_COLOR_SPACE, &color_metadata) != 0) {
+          *color_space = 0;
+      }
+#endif
+    } break;
+    case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO: {
+      private_handle_t *hnd = va_arg(args, private_handle_t *);
+      android_ycbcr *ycbcr = va_arg(args, struct android_ycbcr *);
+      if (private_handle_t::validate(hnd) != 0) {
+        return GRALLOC1_ERROR_BAD_HANDLE;
+      }
+      if (GetYUVPlaneInfo(hnd, ycbcr)) {
+        return GRALLOC1_ERROR_UNDEFINED;
+      }
+    } break;
+
+    case GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO: {
+      private_handle_t *hnd = va_arg(args, private_handle_t *);
+      int *map_secure_buffer = va_arg(args, int *);
+      if (private_handle_t::validate(hnd) != 0) {
+        return GRALLOC1_ERROR_BAD_HANDLE;
+      }
+
+      if (getMetaData(hnd, GET_MAP_SECURE_BUFFER, map_secure_buffer) == 0) {
+        *map_secure_buffer = 0;
+      }
+    } break;
+
+    case GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG: {
+      private_handle_t *hnd = va_arg(args, private_handle_t *);
+      int *flag = va_arg(args, int *);
+      if (private_handle_t::validate(hnd) != 0) {
+        return GRALLOC1_ERROR_BAD_HANDLE;
+      }
+      *flag = hnd->flags &private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+    } break;
+
+    case GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS: {
+      private_handle_t *hnd = va_arg(args, private_handle_t *);
+      void **rgb_data = va_arg(args, void **);
+      if (private_handle_t::validate(hnd) != 0) {
+        return GRALLOC1_ERROR_BAD_HANDLE;
+      }
+      if (GetRgbDataAddress(hnd, rgb_data)) {
+        return GRALLOC1_ERROR_UNDEFINED;
+      }
+    } break;
+
+    case GRALLOC1_MODULE_PERFORM_GET_BUFFER_SIZE_AND_DIMENSIONS: {
+      int width = va_arg(args, int);
+      int height = va_arg(args, int);
+      int format = va_arg(args, int);
+      uint64_t p_usage = va_arg(args, uint64_t);
+      uint64_t c_usage = va_arg(args, uint64_t);
+      gralloc1_producer_usage_t producer_usage = static_cast<gralloc1_producer_usage_t>(p_usage);
+      gralloc1_consumer_usage_t consumer_usage = static_cast<gralloc1_consumer_usage_t>(c_usage);
+      uint32_t *aligned_width = va_arg(args, uint32_t *);
+      uint32_t *aligned_height = va_arg(args, uint32_t *);
+      uint32_t *size = va_arg(args, uint32_t *);
+      auto info = BufferInfo(width, height, format, producer_usage, consumer_usage);
+      GetBufferSizeAndDimensions(info, size, aligned_width, aligned_height);
+      // Align size
+      auto align = GetDataAlignment(format, producer_usage, consumer_usage);
+      *size = ALIGN(*size, align);
+    } break;
+
+      // TODO(user): Break out similar functionality, preferably moving to a common lib.
+
+    case GRALLOC1_MODULE_PERFORM_ALLOCATE_BUFFER: {
+      int width = va_arg(args, int);
+      int height = va_arg(args, int);
+      int format = va_arg(args, int);
+      uint64_t p_usage = va_arg(args, uint64_t);
+      uint64_t c_usage = va_arg(args, uint64_t);
+      buffer_handle_t *hnd = va_arg(args, buffer_handle_t*);
+      gralloc1_producer_usage_t producer_usage = static_cast<gralloc1_producer_usage_t>(p_usage);
+      gralloc1_consumer_usage_t consumer_usage = static_cast<gralloc1_consumer_usage_t>(c_usage);
+      BufferDescriptor descriptor(width, height, format, producer_usage, consumer_usage);
+      unsigned int size;
+      unsigned int alignedw, alignedh;
+      GetBufferSizeAndDimensions(GetBufferInfo(descriptor), &size, &alignedw, &alignedh);
+      AllocateBuffer(descriptor, hnd, size);
+    } break;
+
+    case GRALLOC1_MODULE_PERFORM_GET_INTERLACE_FLAG: {
+      private_handle_t *hnd = va_arg(args, private_handle_t *);
+      int *flag = va_arg(args, int *);
+      if (private_handle_t::validate(hnd) != 0) {
+        return GRALLOC1_ERROR_BAD_HANDLE;
+      }
+      if (getMetaData(hnd, GET_PP_PARAM_INTERLACED, flag) != 0) {
+        *flag = 0;
+      }
+    } break;
+
+    default:
+      break;
+  }
+  return GRALLOC1_ERROR_NONE;
+}
+
+static bool IsYuvFormat(const private_handle_t *hnd) {
+  switch (hnd->format) {
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:   // Same as YCbCr_420_SP_VENUS
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+    case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+    case HAL_PIXEL_FORMAT_NV21_ZSL:
+    case HAL_PIXEL_FORMAT_RAW16:
+    case HAL_PIXEL_FORMAT_Y16:
+    case HAL_PIXEL_FORMAT_RAW12:
+    case HAL_PIXEL_FORMAT_RAW10:
+    case HAL_PIXEL_FORMAT_YV12:
+    case HAL_PIXEL_FORMAT_Y8:
+      return true;
+    default:
+      return false;
+  }
+}
+
+gralloc1_error_t BufferManager::GetNumFlexPlanes(const private_handle_t *hnd,
+                                                 uint32_t *out_num_planes) {
+  if (!IsYuvFormat(hnd)) {
+    return GRALLOC1_ERROR_UNSUPPORTED;
+  } else {
+    *out_num_planes = 3;
+  }
+  return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t BufferManager::GetFlexLayout(const private_handle_t *hnd,
+                                              struct android_flex_layout *layout) {
+  if (!IsYuvFormat(hnd)) {
+    return GRALLOC1_ERROR_UNSUPPORTED;
+  }
+
+  android_ycbcr ycbcr;
+  int err = GetYUVPlaneInfo(hnd, &ycbcr);
+
+  if (err != 0) {
+    return GRALLOC1_ERROR_BAD_HANDLE;
+  }
+
+  layout->format = FLEX_FORMAT_YCbCr;
+  layout->num_planes = 3;
+
+  for (uint32_t i = 0; i < layout->num_planes; i++) {
+    layout->planes[i].bits_per_component = 8;
+    layout->planes[i].bits_used = 8;
+    layout->planes[i].h_increment = 1;
+    layout->planes[i].v_increment = 1;
+    layout->planes[i].h_subsampling = 2;
+    layout->planes[i].v_subsampling = 2;
+  }
+
+  layout->planes[0].top_left = static_cast<uint8_t *>(ycbcr.y);
+  layout->planes[0].component = FLEX_COMPONENT_Y;
+  layout->planes[0].v_increment = static_cast<int32_t>(ycbcr.ystride);
+
+  layout->planes[1].top_left = static_cast<uint8_t *>(ycbcr.cb);
+  layout->planes[1].component = FLEX_COMPONENT_Cb;
+  layout->planes[1].h_increment = static_cast<int32_t>(ycbcr.chroma_step);
+  layout->planes[1].v_increment = static_cast<int32_t>(ycbcr.cstride);
+
+  layout->planes[2].top_left = static_cast<uint8_t *>(ycbcr.cr);
+  layout->planes[2].component = FLEX_COMPONENT_Cr;
+  layout->planes[2].h_increment = static_cast<int32_t>(ycbcr.chroma_step);
+  layout->planes[2].v_increment = static_cast<int32_t>(ycbcr.cstride);
+  return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t BufferManager::Dump(std::ostringstream *os) {
+  for (auto it : handles_map_) {
+    auto buf = it.second;
+    auto hnd = buf->handle;
+    *os << "handle id: " << std::setw(4) << hnd->id;
+    *os << " fd: "       << std::setw(3) << hnd->fd;
+    *os << " fd_meta: "  << std::setw(3) << hnd->fd_metadata;
+    *os << " wxh: "      << std::setw(4) << hnd->width <<" x " << std::setw(4) <<  hnd->height;
+    *os << " uwxuh: "    << std::setw(4) << hnd->unaligned_width << " x ";
+    *os << std::setw(4)  <<  hnd->unaligned_height;
+    *os << " size: "     << std::setw(9) << hnd->size;
+    *os << std::hex << std::setfill('0');
+    *os << " priv_flags: " << "0x" << std::setw(8) << hnd->flags;
+    *os << " prod_usage: " << "0x" << std::setw(8) << hnd->producer_usage;
+    *os << " cons_usage: " << "0x" << std::setw(8) << hnd->consumer_usage;
+    // TODO(user): get format string from qdutils
+    *os << " format: "     << "0x" << std::setw(8) << hnd->format;
+    *os << std::dec  << std::setfill(' ') << std::endl;
+  }
+  return GRALLOC1_ERROR_NONE;
+}
+}  //  namespace gralloc1
diff --git a/sdm845/libgralloc1/gr_buf_mgr.h b/sdm845/libgralloc1/gr_buf_mgr.h
new file mode 100644
index 0000000..4476eaf
--- /dev/null
+++ b/sdm845/libgralloc1/gr_buf_mgr.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __GR_BUF_MGR_H__
+#define __GR_BUF_MGR_H__
+
+#include <pthread.h>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <mutex>
+
+#include "gralloc_priv.h"
+#include "gr_allocator.h"
+#include "gr_buf_descriptor.h"
+
+namespace gralloc1 {
+
+class BufferManager {
+ public:
+  ~BufferManager();
+  gralloc1_error_t CreateBufferDescriptor(gralloc1_buffer_descriptor_t *descriptor_id);
+  gralloc1_error_t DestroyBufferDescriptor(gralloc1_buffer_descriptor_t descriptor_id);
+  gralloc1_error_t AllocateBuffers(uint32_t num_descriptors,
+                                   const gralloc1_buffer_descriptor_t *descriptor_ids,
+                                   buffer_handle_t *out_buffers);
+  gralloc1_error_t RetainBuffer(private_handle_t const *hnd);
+  gralloc1_error_t ReleaseBuffer(private_handle_t const *hnd);
+  gralloc1_error_t LockBuffer(const private_handle_t *hnd, gralloc1_producer_usage_t prod_usage,
+                              gralloc1_consumer_usage_t cons_usage);
+  gralloc1_error_t UnlockBuffer(const private_handle_t *hnd);
+  gralloc1_error_t Perform(int operation, va_list args);
+  gralloc1_error_t GetFlexLayout(const private_handle_t *hnd, struct android_flex_layout *layout);
+  gralloc1_error_t GetNumFlexPlanes(const private_handle_t *hnd, uint32_t *out_num_planes);
+  gralloc1_error_t Dump(std::ostringstream *os);
+
+  template <typename... Args>
+  gralloc1_error_t CallBufferDescriptorFunction(gralloc1_buffer_descriptor_t descriptor_id,
+                                                void (BufferDescriptor::*member)(Args...),
+                                                Args... args) {
+    std::lock_guard<std::mutex> lock(descriptor_lock_);
+    const auto map_descriptor = descriptors_map_.find(descriptor_id);
+    if (map_descriptor == descriptors_map_.end()) {
+      return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+    }
+    const auto descriptor = map_descriptor->second;
+    (descriptor.get()->*member)(std::forward<Args>(args)...);
+    return GRALLOC1_ERROR_NONE;
+  }
+
+  static BufferManager* GetInstance() {
+    static BufferManager *instance = new BufferManager();
+    return instance;
+  }
+
+ private:
+  BufferManager();
+  gralloc1_error_t MapBuffer(private_handle_t const *hnd);
+  int GetBufferType(int format);
+  int AllocateBuffer(const BufferDescriptor &descriptor, buffer_handle_t *handle,
+                     unsigned int bufferSize = 0);
+  uint32_t GetDataAlignment(int format, gralloc1_producer_usage_t prod_usage,
+                       gralloc1_consumer_usage_t cons_usage);
+  int GetHandleFlags(int format, gralloc1_producer_usage_t prod_usage,
+                     gralloc1_consumer_usage_t cons_usage);
+  void CreateSharedHandle(buffer_handle_t inbuffer, const BufferDescriptor &descriptor,
+                          buffer_handle_t *out_buffer);
+
+  // Imports the ion fds into the current process. Returns an error for invalid handles
+  gralloc1_error_t ImportHandleLocked(private_handle_t *hnd);
+
+  // Creates a Buffer from the valid private handle and adds it to the map
+  void RegisterHandleLocked(const private_handle_t *hnd, int ion_handle, int ion_handle_meta);
+
+  // Wrapper structure over private handle
+  // Values associated with the private handle
+  // that do not need to go over IPC can be placed here
+  // This structure is also not expected to be ABI stable
+  // unlike private_handle_t
+  struct Buffer {
+    const private_handle_t *handle = nullptr;
+    int ref_count = 1;
+    // Hold the main and metadata ion handles
+    // Freed from the allocator process
+    // and unused in the mapping process
+    int ion_handle_main = -1;
+    int ion_handle_meta = -1;
+
+    Buffer() = delete;
+    explicit Buffer(const private_handle_t* h, int ih_main = -1, int ih_meta = -1):
+        handle(h),
+        ion_handle_main(ih_main),
+        ion_handle_meta(ih_meta) {
+    }
+    void IncRef() { ++ref_count; }
+    bool DecRef() { return --ref_count == 0; }
+  };
+
+  gralloc1_error_t FreeBuffer(std::shared_ptr<Buffer> buf);
+
+  // Get the wrapper Buffer object from the handle, returns nullptr if handle is not found
+  std::shared_ptr<Buffer> GetBufferFromHandleLocked(const private_handle_t *hnd);
+
+  bool map_fb_mem_ = false;
+  bool ubwc_for_fb_ = false;
+  Allocator *allocator_ = NULL;
+  std::mutex buffer_lock_;
+  std::mutex descriptor_lock_;
+  // TODO(user): The private_handle_t is used as a key because the unique ID generated
+  // from next_id_ is not unique across processes. The correct way to resolve this would
+  // be to use the allocator over hwbinder
+  std::unordered_map<const private_handle_t*, std::shared_ptr<Buffer>> handles_map_ = {};
+  std::unordered_map<gralloc1_buffer_descriptor_t,
+                     std::shared_ptr<BufferDescriptor>> descriptors_map_ = {};
+  std::atomic<uint64_t> next_id_;
+};
+
+}  // namespace gralloc1
+
+#endif  // __GR_BUF_MGR_H__
diff --git a/sdm845/libgralloc1/gr_device_impl.cpp b/sdm845/libgralloc1/gr_device_impl.cpp
new file mode 100644
index 0000000..ee90090
--- /dev/null
+++ b/sdm845/libgralloc1/gr_device_impl.cpp
@@ -0,0 +1,513 @@
+/*
+ * Copyright (c) 2016-2017, 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 ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+#include <cutils/log.h>
+#include <utils/Trace.h>
+#include <cutils/trace.h>
+#include <sync/sync.h>
+#include <algorithm>
+#include <sstream>
+#include <string>
+
+#include "gr_device_impl.h"
+#include "gr_buf_descriptor.h"
+#include "gralloc_priv.h"
+#include "qd_utils.h"
+#include "qdMetaData.h"
+#include "gr_utils.h"
+
+int gralloc_device_open(const struct hw_module_t *module, const char *name, hw_device_t **device);
+
+int gralloc_device_close(struct hw_device_t *device);
+
+static struct hw_module_methods_t gralloc_module_methods = {.open = gralloc_device_open};
+
+struct gralloc_module_t HAL_MODULE_INFO_SYM = {
+  .common = {
+    .tag = HARDWARE_MODULE_TAG,
+    .module_api_version = GRALLOC_MODULE_API_VERSION_1_0,
+    .hal_api_version    = HARDWARE_HAL_API_VERSION,
+    .id = GRALLOC_HARDWARE_MODULE_ID,
+    .name = "Graphics Memory Module",
+    .author = "Code Aurora Forum",
+    .methods = &gralloc_module_methods,
+    .dso = 0,
+    .reserved = {0},
+  },
+};
+
+int gralloc_device_open(const struct hw_module_t *module, const char *name, hw_device_t **device) {
+  int status = -EINVAL;
+  if (!strcmp(name, GRALLOC_HARDWARE_MODULE_ID)) {
+    gralloc1::GrallocImpl * /*gralloc1_device_t*/ dev = gralloc1::GrallocImpl::GetInstance(module);
+    *device = reinterpret_cast<hw_device_t *>(dev);
+    if (dev) {
+      status = 0;
+    } else {
+      ALOGE("Fatal error opening gralloc1 device");
+    }
+  }
+  return status;
+}
+
+namespace gralloc1 {
+
+GrallocImpl::GrallocImpl(const hw_module_t *module) {
+  common.tag = HARDWARE_DEVICE_TAG;
+  common.version = GRALLOC_MODULE_API_VERSION_1_0;
+  common.module = const_cast<hw_module_t *>(module);
+  common.close = CloseDevice;
+  getFunction = GetFunction;
+  getCapabilities = GetCapabilities;
+
+  initalized_ = Init();
+}
+
+bool GrallocImpl::Init() {
+  buf_mgr_ = BufferManager::GetInstance();
+  return buf_mgr_ != nullptr;
+}
+
+GrallocImpl::~GrallocImpl() {
+}
+
+int GrallocImpl::CloseDevice(hw_device_t *device __unused) {
+  // No-op since the gralloc device is a singleton
+  return 0;
+}
+
+void GrallocImpl::GetCapabilities(struct gralloc1_device *device, uint32_t *out_count,
+                                  int32_t  /*gralloc1_capability_t*/ *out_capabilities) {
+  if (device != nullptr) {
+    if (out_capabilities != nullptr && *out_count >= 3) {
+      out_capabilities[0] = GRALLOC1_CAPABILITY_TEST_ALLOCATE;
+      out_capabilities[1] = GRALLOC1_CAPABILITY_LAYERED_BUFFERS;
+      out_capabilities[2] = GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE;
+    }
+    *out_count = 3;
+  }
+  return;
+}
+
+gralloc1_function_pointer_t GrallocImpl::GetFunction(gralloc1_device_t *device, int32_t function) {
+  if (!device) {
+    return NULL;
+  }
+
+  switch (function) {
+    case GRALLOC1_FUNCTION_DUMP:
+      return reinterpret_cast<gralloc1_function_pointer_t>(Dump);
+    case GRALLOC1_FUNCTION_CREATE_DESCRIPTOR:
+      return reinterpret_cast<gralloc1_function_pointer_t>(CreateBufferDescriptor);
+    case GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR:
+      return reinterpret_cast<gralloc1_function_pointer_t>(DestroyBufferDescriptor);
+    case GRALLOC1_FUNCTION_SET_CONSUMER_USAGE:
+      return reinterpret_cast<gralloc1_function_pointer_t>(SetConsumerUsage);
+    case GRALLOC1_FUNCTION_SET_DIMENSIONS:
+      return reinterpret_cast<gralloc1_function_pointer_t>(SetBufferDimensions);
+    case GRALLOC1_FUNCTION_SET_FORMAT:
+      return reinterpret_cast<gralloc1_function_pointer_t>(SetColorFormat);
+    case GRALLOC1_FUNCTION_SET_LAYER_COUNT:
+      return reinterpret_cast<gralloc1_function_pointer_t>(SetLayerCount);
+    case GRALLOC1_FUNCTION_SET_PRODUCER_USAGE:
+      return reinterpret_cast<gralloc1_function_pointer_t>(SetProducerUsage);
+    case GRALLOC1_FUNCTION_GET_BACKING_STORE:
+      return reinterpret_cast<gralloc1_function_pointer_t>(GetBackingStore);
+    case GRALLOC1_FUNCTION_GET_CONSUMER_USAGE:
+      return reinterpret_cast<gralloc1_function_pointer_t>(GetConsumerUsage);
+    case GRALLOC1_FUNCTION_GET_DIMENSIONS:
+      return reinterpret_cast<gralloc1_function_pointer_t>(GetBufferDimensions);
+    case GRALLOC1_FUNCTION_GET_FORMAT:
+      return reinterpret_cast<gralloc1_function_pointer_t>(GetColorFormat);
+    case GRALLOC1_FUNCTION_GET_LAYER_COUNT:
+      return reinterpret_cast<gralloc1_function_pointer_t>(GetLayerCount);
+    case GRALLOC1_FUNCTION_GET_PRODUCER_USAGE:
+      return reinterpret_cast<gralloc1_function_pointer_t>(GetProducerUsage);
+    case GRALLOC1_FUNCTION_GET_STRIDE:
+      return reinterpret_cast<gralloc1_function_pointer_t>(GetBufferStride);
+    case GRALLOC1_FUNCTION_ALLOCATE:
+      return reinterpret_cast<gralloc1_function_pointer_t>(AllocateBuffers);
+    case GRALLOC1_FUNCTION_RETAIN:
+      return reinterpret_cast<gralloc1_function_pointer_t>(RetainBuffer);
+    case GRALLOC1_FUNCTION_RELEASE:
+      return reinterpret_cast<gralloc1_function_pointer_t>(ReleaseBuffer);
+    case GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES:
+      return reinterpret_cast<gralloc1_function_pointer_t>(GetNumFlexPlanes);
+    case GRALLOC1_FUNCTION_LOCK:
+      return reinterpret_cast<gralloc1_function_pointer_t>(LockBuffer);
+    case GRALLOC1_FUNCTION_LOCK_FLEX:
+      return reinterpret_cast<gralloc1_function_pointer_t>(LockFlex);
+    case GRALLOC1_FUNCTION_UNLOCK:
+      return reinterpret_cast<gralloc1_function_pointer_t>(UnlockBuffer);
+    case GRALLOC1_FUNCTION_PERFORM:
+      return reinterpret_cast<gralloc1_function_pointer_t>(Gralloc1Perform);
+    default:
+      ALOGE("%s:Gralloc Error. Client Requested for unsupported function", __FUNCTION__);
+      return NULL;
+  }
+
+  return NULL;
+}
+
+gralloc1_error_t GrallocImpl::Dump(gralloc1_device_t *device, uint32_t *out_size,
+                                   char *out_buffer) {
+  if (!device) {
+    ALOGE("Gralloc Error : device=%p", (void *)device);
+    return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+  }
+  const size_t max_dump_size = 8192;
+  if (out_buffer == nullptr) {
+    *out_size = max_dump_size;
+  } else {
+    std::ostringstream os;
+    os << "-------------------------------" << std::endl;
+    os << "QTI gralloc dump:" << std::endl;
+    os << "-------------------------------" << std::endl;
+    GrallocImpl const *dev = GRALLOC_IMPL(device);
+    dev->buf_mgr_->Dump(&os);
+    os << "-------------------------------" << std::endl;
+    auto copied = os.str().copy(out_buffer, std::min(os.str().size(), max_dump_size), 0);
+    *out_size = UINT(copied);
+  }
+
+  return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t GrallocImpl::CheckDeviceAndHandle(gralloc1_device_t *device,
+                                                   buffer_handle_t buffer) {
+  const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+  if (!device || (private_handle_t::validate(hnd) != 0)) {
+    ALOGE("Gralloc Error : device= %p, buffer-handle=%p", (void *)device, (void *)buffer);
+    return GRALLOC1_ERROR_BAD_HANDLE;
+  }
+
+  return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t GrallocImpl::CreateBufferDescriptor(gralloc1_device_t *device,
+                                                     gralloc1_buffer_descriptor_t *out_descriptor) {
+  if (!device) {
+    return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+  }
+  GrallocImpl const *dev = GRALLOC_IMPL(device);
+  return dev->buf_mgr_->CreateBufferDescriptor(out_descriptor);
+}
+
+gralloc1_error_t GrallocImpl::DestroyBufferDescriptor(gralloc1_device_t *device,
+                                                      gralloc1_buffer_descriptor_t descriptor) {
+  if (!device) {
+    return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+  }
+  GrallocImpl const *dev = GRALLOC_IMPL(device);
+  return dev->buf_mgr_->DestroyBufferDescriptor(descriptor);
+}
+
+gralloc1_error_t GrallocImpl::SetConsumerUsage(gralloc1_device_t *device,
+                                               gralloc1_buffer_descriptor_t descriptor,
+                                               gralloc1_consumer_usage_t usage) {
+  if (!device) {
+    return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+  } else {
+    GrallocImpl const *dev = GRALLOC_IMPL(device);
+    return dev->buf_mgr_->CallBufferDescriptorFunction(descriptor,
+                                                       &BufferDescriptor::SetConsumerUsage, usage);
+  }
+}
+
+gralloc1_error_t GrallocImpl::SetBufferDimensions(gralloc1_device_t *device,
+                                                  gralloc1_buffer_descriptor_t descriptor,
+                                                  uint32_t width, uint32_t height) {
+  if (!device) {
+    return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+  } else {
+    GrallocImpl const *dev = GRALLOC_IMPL(device);
+    return dev->buf_mgr_->CallBufferDescriptorFunction(descriptor,
+                                                       &BufferDescriptor::SetDimensions,
+                                                       INT(width), INT(height));
+  }
+}
+
+gralloc1_error_t GrallocImpl::SetColorFormat(gralloc1_device_t *device,
+                                             gralloc1_buffer_descriptor_t descriptor,
+                                             int32_t format) {
+  if (!device) {
+    return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+  } else {
+    GrallocImpl const *dev = GRALLOC_IMPL(device);
+    return dev->buf_mgr_->CallBufferDescriptorFunction(descriptor,
+                                                       &BufferDescriptor::SetColorFormat, format);
+  }
+}
+
+gralloc1_error_t GrallocImpl::SetLayerCount(gralloc1_device_t *device,
+                                            gralloc1_buffer_descriptor_t descriptor,
+                                            uint32_t layer_count) {
+  if (!device) {
+    return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+  } else {
+    GrallocImpl const *dev = GRALLOC_IMPL(device);
+    return dev->buf_mgr_->CallBufferDescriptorFunction(descriptor,
+                                                       &BufferDescriptor::SetLayerCount,
+                                                       layer_count);
+  }
+}
+
+gralloc1_error_t GrallocImpl::SetProducerUsage(gralloc1_device_t *device,
+                                               gralloc1_buffer_descriptor_t descriptor,
+                                               gralloc1_producer_usage_t usage) {
+  if (!device) {
+    return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+  } else {
+    GrallocImpl const *dev = GRALLOC_IMPL(device);
+    return dev->buf_mgr_->CallBufferDescriptorFunction(descriptor,
+                                                       &BufferDescriptor::SetProducerUsage, usage);
+  }
+}
+
+gralloc1_error_t GrallocImpl::GetBackingStore(gralloc1_device_t *device, buffer_handle_t buffer,
+                                              gralloc1_backing_store_t *out_backstore) {
+  if (!device || !buffer) {
+    return GRALLOC1_ERROR_BAD_HANDLE;
+  }
+
+  *out_backstore =
+      static_cast<gralloc1_backing_store_t>(PRIV_HANDLE_CONST(buffer)->GetBackingstore());
+
+  return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t GrallocImpl::GetConsumerUsage(gralloc1_device_t *device, buffer_handle_t buffer,
+                                               gralloc1_consumer_usage_t *outUsage) {
+  gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+  if (status == GRALLOC1_ERROR_NONE) {
+    *outUsage = PRIV_HANDLE_CONST(buffer)->GetConsumerUsage();
+  }
+
+  return status;
+}
+
+gralloc1_error_t GrallocImpl::GetBufferDimensions(gralloc1_device_t *device, buffer_handle_t buffer,
+                                                  uint32_t *outWidth, uint32_t *outHeight) {
+  gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+  if (status == GRALLOC1_ERROR_NONE) {
+    const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+    *outWidth = UINT(hnd->GetUnalignedWidth());
+    *outHeight = UINT(hnd->GetUnalignedHeight());
+  }
+
+  return status;
+}
+
+gralloc1_error_t GrallocImpl::GetColorFormat(gralloc1_device_t *device, buffer_handle_t buffer,
+                                             int32_t *outFormat) {
+  gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+  if (status == GRALLOC1_ERROR_NONE) {
+    *outFormat = PRIV_HANDLE_CONST(buffer)->GetColorFormat();
+  }
+
+  return status;
+}
+
+gralloc1_error_t GrallocImpl::GetLayerCount(gralloc1_device_t *device, buffer_handle_t buffer,
+                                            uint32_t *outLayerCount) {
+  gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+  if (status == GRALLOC1_ERROR_NONE) {
+    *outLayerCount = PRIV_HANDLE_CONST(buffer)->GetLayerCount();
+  }
+
+  return status;
+}
+
+gralloc1_error_t GrallocImpl::GetProducerUsage(gralloc1_device_t *device, buffer_handle_t buffer,
+                                               gralloc1_producer_usage_t *outUsage) {
+  gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+  if (status == GRALLOC1_ERROR_NONE) {
+    const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+    *outUsage = hnd->GetProducerUsage();
+  }
+
+  return status;
+}
+
+gralloc1_error_t GrallocImpl::GetBufferStride(gralloc1_device_t *device, buffer_handle_t buffer,
+                                              uint32_t *outStride) {
+  gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+  if (status == GRALLOC1_ERROR_NONE) {
+    *outStride = UINT(PRIV_HANDLE_CONST(buffer)->GetStride());
+  }
+
+  return status;
+}
+
+gralloc1_error_t GrallocImpl::AllocateBuffers(gralloc1_device_t *device, uint32_t num_descriptors,
+                                              const gralloc1_buffer_descriptor_t *descriptors,
+                                              buffer_handle_t *out_buffers) {
+  if (!num_descriptors || !descriptors) {
+    return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+  }
+
+  GrallocImpl const *dev = GRALLOC_IMPL(device);
+  gralloc1_error_t status = dev->buf_mgr_->AllocateBuffers(num_descriptors, descriptors,
+                                                           out_buffers);
+
+  return status;
+}
+
+gralloc1_error_t GrallocImpl::RetainBuffer(gralloc1_device_t *device, buffer_handle_t buffer) {
+  gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+  if (status == GRALLOC1_ERROR_NONE) {
+    const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+    GrallocImpl const *dev = GRALLOC_IMPL(device);
+    status = dev->buf_mgr_->RetainBuffer(hnd);
+  }
+
+  return status;
+}
+
+gralloc1_error_t GrallocImpl::ReleaseBuffer(gralloc1_device_t *device, buffer_handle_t buffer) {
+  gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+  if (status == GRALLOC1_ERROR_NONE) {
+    const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+    GrallocImpl const *dev = GRALLOC_IMPL(device);
+    status = dev->buf_mgr_->ReleaseBuffer(hnd);
+  }
+
+  return status;
+}
+
+gralloc1_error_t GrallocImpl::GetNumFlexPlanes(gralloc1_device_t *device, buffer_handle_t buffer,
+                                               uint32_t *out_num_planes) {
+  gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+  if (status == GRALLOC1_ERROR_NONE) {
+    GrallocImpl const *dev = GRALLOC_IMPL(device);
+    const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+    status = dev->buf_mgr_->GetNumFlexPlanes(hnd, out_num_planes);
+  }
+  return status;
+}
+
+static inline void CloseFdIfValid(int fd) {
+  if (fd > 0) {
+    close(fd);
+  }
+}
+
+gralloc1_error_t GrallocImpl::LockBuffer(gralloc1_device_t *device, buffer_handle_t buffer,
+                                         gralloc1_producer_usage_t prod_usage,
+                                         gralloc1_consumer_usage_t cons_usage,
+                                         const gralloc1_rect_t *region, void **out_data,
+                                         int32_t acquire_fence) {
+  ATRACE_CALL();
+  gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+  if (status != GRALLOC1_ERROR_NONE) {
+    CloseFdIfValid(acquire_fence);
+    return status;
+  }
+
+  if (acquire_fence > 0) {
+    ATRACE_BEGIN("fence wait");
+    int error = sync_wait(acquire_fence, 1000);
+    ATRACE_END();
+    CloseFdIfValid(acquire_fence);
+    if (error < 0) {
+      ALOGE("%s: sync_wait timedout! error = %s", __FUNCTION__, strerror(errno));
+      return GRALLOC1_ERROR_UNDEFINED;
+    }
+  }
+
+  const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+  GrallocImpl const *dev = GRALLOC_IMPL(device);
+
+  // Either producer usage or consumer usage must be *_USAGE_NONE
+  if ((prod_usage != GRALLOC1_PRODUCER_USAGE_NONE) &&
+      (cons_usage != GRALLOC1_CONSUMER_USAGE_NONE)) {
+    // Current gralloc1 clients do not satisfy this restriction.
+    // See b/33588773 for details
+    // return GRALLOC1_ERROR_BAD_VALUE;
+  }
+
+  // currently we ignore the region/rect client wants to lock
+  if (region == NULL) {
+    return GRALLOC1_ERROR_BAD_VALUE;
+  }
+  // TODO(user): Need to check if buffer was allocated with the same flags
+  status = dev->buf_mgr_->LockBuffer(hnd, prod_usage, cons_usage);
+
+  *out_data = reinterpret_cast<void *>(hnd->base);
+
+  return status;
+}
+
+gralloc1_error_t GrallocImpl::LockFlex(gralloc1_device_t *device, buffer_handle_t buffer,
+                                       gralloc1_producer_usage_t prod_usage,
+                                       gralloc1_consumer_usage_t cons_usage,
+                                       const gralloc1_rect_t *region,
+                                       struct android_flex_layout *out_flex_layout,
+                                       int32_t acquire_fence) {
+  void *out_data;
+  gralloc1_error_t status = GrallocImpl::LockBuffer(device, buffer, prod_usage, cons_usage, region,
+                                                    &out_data, acquire_fence);
+  if (status != GRALLOC1_ERROR_NONE) {
+    return status;
+  }
+
+  GrallocImpl const *dev = GRALLOC_IMPL(device);
+  const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+  dev->buf_mgr_->GetFlexLayout(hnd, out_flex_layout);
+  return status;
+}
+
+gralloc1_error_t GrallocImpl::UnlockBuffer(gralloc1_device_t *device, buffer_handle_t buffer,
+                                           int32_t *release_fence) {
+  gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
+
+  if (status != GRALLOC1_ERROR_NONE) {
+    return status;
+  }
+
+  const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+  GrallocImpl const *dev = GRALLOC_IMPL(device);
+
+  *release_fence = -1;
+
+  return dev->buf_mgr_->UnlockBuffer(hnd);
+}
+
+gralloc1_error_t GrallocImpl::Gralloc1Perform(gralloc1_device_t *device, int operation, ...) {
+  va_list args;
+  va_start(args, operation);
+  GrallocImpl const *dev = GRALLOC_IMPL(device);
+  gralloc1_error_t err = dev->buf_mgr_->Perform(operation, args);
+  va_end(args);
+
+  return err;
+}
+
+}  // namespace gralloc1
diff --git a/sdm845/libgralloc1/gr_device_impl.h b/sdm845/libgralloc1/gr_device_impl.h
new file mode 100644
index 0000000..55ce44b
--- /dev/null
+++ b/sdm845/libgralloc1/gr_device_impl.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2016-2017, 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 __GR_DEVICE_IMPL_H__
+#define __GR_DEVICE_IMPL_H__
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc1.h>
+#include "gr_buf_mgr.h"
+
+struct private_module_t {
+  hw_module_t base;
+};
+
+#define GRALLOC_IMPL(exp) reinterpret_cast<GrallocImpl const *>(exp)
+
+namespace gralloc1 {
+
+class GrallocImpl : public gralloc1_device_t {
+ public:
+  static int CloseDevice(hw_device_t *device);
+  static void GetCapabilities(struct gralloc1_device *device, uint32_t *out_count,
+                              int32_t * /*gralloc1_capability_t*/ out_capabilities);
+  static gralloc1_function_pointer_t GetFunction(
+      struct gralloc1_device *device, int32_t /*gralloc1_function_descriptor_t*/ descriptor);
+
+  static GrallocImpl* GetInstance(const struct hw_module_t *module) {
+    static GrallocImpl *instance = new GrallocImpl(module);
+    if (instance->IsInitialized()) {
+      return instance;
+    } else {
+      return nullptr;
+    }
+  }
+
+ private:
+  static inline gralloc1_error_t Dump(gralloc1_device_t *device, uint32_t *out_size,
+                                      char *out_buffer);
+  static inline gralloc1_error_t CheckDeviceAndHandle(gralloc1_device_t *device,
+                                                      buffer_handle_t buffer);
+  static gralloc1_error_t CreateBufferDescriptor(gralloc1_device_t *device,
+                                                 gralloc1_buffer_descriptor_t *out_descriptor);
+  static gralloc1_error_t DestroyBufferDescriptor(gralloc1_device_t *device,
+                                                  gralloc1_buffer_descriptor_t descriptor);
+  static gralloc1_error_t SetConsumerUsage(gralloc1_device_t *device,
+                                           gralloc1_buffer_descriptor_t descriptor,
+                                           gralloc1_consumer_usage_t usage);
+  static gralloc1_error_t SetBufferDimensions(gralloc1_device_t *device,
+                                              gralloc1_buffer_descriptor_t descriptor,
+                                              uint32_t width, uint32_t height);
+  static gralloc1_error_t SetColorFormat(gralloc1_device_t *device,
+                                         gralloc1_buffer_descriptor_t descriptor, int32_t format);
+  static gralloc1_error_t SetLayerCount(gralloc1_device_t *device,
+                                        gralloc1_buffer_descriptor_t descriptor,
+                                        uint32_t layer_count);
+  static gralloc1_error_t SetProducerUsage(gralloc1_device_t *device,
+                                           gralloc1_buffer_descriptor_t descriptor,
+                                           gralloc1_producer_usage_t usage);
+  static gralloc1_error_t GetBackingStore(gralloc1_device_t *device, buffer_handle_t buffer,
+                                          gralloc1_backing_store_t *out_store);
+  static gralloc1_error_t GetConsumerUsage(gralloc1_device_t *device, buffer_handle_t buffer,
+                                           gralloc1_consumer_usage_t *out_usage);
+  static gralloc1_error_t GetBufferDimensions(gralloc1_device_t *device, buffer_handle_t buffer,
+                                              uint32_t *out_width, uint32_t *out_height);
+  static gralloc1_error_t GetColorFormat(gralloc1_device_t *device, buffer_handle_t descriptor,
+                                         int32_t *outFormat);
+  static gralloc1_error_t GetLayerCount(gralloc1_device_t *device, buffer_handle_t buffer,
+                                        uint32_t *out_layer_count);
+  static gralloc1_error_t GetProducerUsage(gralloc1_device_t *device, buffer_handle_t buffer,
+                                           gralloc1_producer_usage_t *out_usage);
+  static gralloc1_error_t GetBufferStride(gralloc1_device_t *device, buffer_handle_t buffer,
+                                          uint32_t *out_stride);
+  static gralloc1_error_t AllocateBuffers(gralloc1_device_t *device, uint32_t num_dptors,
+                                          const gralloc1_buffer_descriptor_t *descriptors,
+                                          buffer_handle_t *out_buffers);
+  static gralloc1_error_t RetainBuffer(gralloc1_device_t *device, buffer_handle_t buffer);
+  static gralloc1_error_t ReleaseBuffer(gralloc1_device_t *device, buffer_handle_t buffer);
+  static gralloc1_error_t GetNumFlexPlanes(gralloc1_device_t *device, buffer_handle_t buffer,
+                                           uint32_t *out_num_planes);
+  static gralloc1_error_t LockBuffer(gralloc1_device_t *device, buffer_handle_t buffer,
+                                     gralloc1_producer_usage_t prod_usage,
+                                     gralloc1_consumer_usage_t cons_usage,
+                                     const gralloc1_rect_t *region, void **out_data,
+                                     int32_t acquire_fence);
+  static gralloc1_error_t LockFlex(gralloc1_device_t *device, buffer_handle_t buffer,
+                                   gralloc1_producer_usage_t prod_usage,
+                                   gralloc1_consumer_usage_t cons_usage,
+                                   const gralloc1_rect_t *region,
+                                   struct android_flex_layout *out_flex_layout,
+                                   int32_t acquire_fence);
+
+  static gralloc1_error_t UnlockBuffer(gralloc1_device_t *device, buffer_handle_t buffer,
+                                       int32_t *release_fence);
+  static gralloc1_error_t Gralloc1Perform(gralloc1_device_t *device, int operation, ...);
+
+  explicit GrallocImpl(const hw_module_t *module);
+  ~GrallocImpl();
+  bool Init();
+  bool IsInitialized() const { return initalized_; }
+
+  BufferManager *buf_mgr_ = NULL;
+  bool initalized_ = false;
+};
+
+}  // namespace gralloc1
+
+#endif  // __GR_DEVICE_IMPL_H__
diff --git a/sdm845/libgralloc1/gr_ion_alloc.cpp b/sdm845/libgralloc1/gr_ion_alloc.cpp
new file mode 100644
index 0000000..c8300ab
--- /dev/null
+++ b/sdm845/libgralloc1/gr_ion_alloc.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2011-2017, 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 DEBUG 0
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <cutils/log.h>
+#include <errno.h>
+#include <utils/Trace.h>
+#include <cutils/trace.h>
+#include <string>
+
+#include "gralloc_priv.h"
+#include "gr_utils.h"
+#include "gr_ion_alloc.h"
+
+namespace gralloc1 {
+
+bool IonAlloc::Init() {
+  if (ion_dev_fd_ == FD_INIT) {
+    ion_dev_fd_ = open(kIonDevice, O_RDONLY);
+  }
+
+  if (ion_dev_fd_ < 0) {
+    ALOGE("%s: Failed to open ion device - %s", __FUNCTION__, strerror(errno));
+    ion_dev_fd_ = FD_INIT;
+    return false;
+  }
+
+  return true;
+}
+
+void IonAlloc::CloseIonDevice() {
+  if (ion_dev_fd_ > FD_INIT) {
+    close(ion_dev_fd_);
+  }
+
+  ion_dev_fd_ = FD_INIT;
+}
+
+int IonAlloc::AllocBuffer(AllocData *data) {
+  ATRACE_CALL();
+  int err = 0;
+  struct ion_handle_data handle_data;
+  struct ion_fd_data fd_data;
+  struct ion_allocation_data ion_alloc_data;
+
+  ion_alloc_data.len = data->size;
+  ion_alloc_data.align = data->align;
+  ion_alloc_data.heap_id_mask = data->heap_id;
+  ion_alloc_data.flags = data->flags;
+  ion_alloc_data.flags |= data->uncached ? 0 : ION_FLAG_CACHED;
+  std::string tag_name{};
+  if (ATRACE_ENABLED()) {
+    tag_name = "ION_IOC_ALLOC size: " + std::to_string(data->size);
+  }
+
+  ATRACE_BEGIN(tag_name.c_str());
+  if (ioctl(ion_dev_fd_, INT(ION_IOC_ALLOC), &ion_alloc_data)) {
+    err = -errno;
+    ALOGE("ION_IOC_ALLOC failed with error - %s", strerror(errno));
+    return err;
+  }
+  ATRACE_END();
+
+  fd_data.handle = ion_alloc_data.handle;
+  handle_data.handle = ion_alloc_data.handle;
+  ATRACE_BEGIN("ION_IOC_MAP");
+  if (ioctl(ion_dev_fd_, INT(ION_IOC_MAP), &fd_data)) {
+    err = -errno;
+    ALOGE("%s: ION_IOC_MAP failed with error - %s", __FUNCTION__, strerror(errno));
+    ioctl(ion_dev_fd_, INT(ION_IOC_FREE), &handle_data);
+    return err;
+  }
+  ATRACE_END();
+
+  data->fd = fd_data.fd;
+  data->ion_handle = handle_data.handle;
+  ALOGD_IF(DEBUG, "ion: Allocated buffer size:%zu fd:%d handle:0x%x",
+          ion_alloc_data.len, data->fd, data->ion_handle);
+
+  return 0;
+}
+
+int IonAlloc::FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd,
+                         int ion_handle) {
+  ATRACE_CALL();
+  int err = 0;
+  ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%u fd:%d handle:0x%x", base, size, fd,
+           ion_handle);
+
+  if (base) {
+    err = UnmapBuffer(base, size, offset);
+  }
+
+  if (ion_handle > 0) {
+    struct ion_handle_data handle_data;
+    handle_data.handle = ion_handle;
+    ioctl(ion_dev_fd_, INT(ION_IOC_FREE), &handle_data);
+  }
+  close(fd);
+  return err;
+}
+
+int IonAlloc::MapBuffer(void **base, unsigned int size, unsigned int offset, int fd) {
+  ATRACE_CALL();
+  int err = 0;
+  void *addr = 0;
+
+  // It is a (quirky) requirement of ION to have opened the
+  // ion fd in the process that is doing the mapping
+  addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  *base = addr;
+  if (addr == MAP_FAILED) {
+    err = -errno;
+    ALOGE("ion: Failed to map memory in the client: %s", strerror(errno));
+  } else {
+    ALOGD_IF(DEBUG, "ion: Mapped buffer base:%p size:%u offset:%u fd:%d", addr, size, offset, fd);
+  }
+
+  return err;
+}
+
+int IonAlloc::ImportBuffer(int fd) {
+  struct ion_fd_data fd_data;
+  int err = 0;
+  fd_data.fd = fd;
+  if (ioctl(ion_dev_fd_, INT(ION_IOC_IMPORT), &fd_data)) {
+    err = -errno;
+    ALOGE("%s: ION_IOC_IMPORT failed with error - %s", __FUNCTION__, strerror(errno));
+    return err;
+  }
+  return fd_data.handle;
+}
+
+int IonAlloc::UnmapBuffer(void *base, unsigned int size, unsigned int /*offset*/) {
+  ATRACE_CALL();
+  ALOGD_IF(DEBUG, "ion: Unmapping buffer  base:%p size:%u", base, size);
+
+  int err = 0;
+  if (munmap(base, size)) {
+    err = -errno;
+    ALOGE("ion: Failed to unmap memory at %p : %s", base, strerror(errno));
+  }
+
+  return err;
+}
+
+int IonAlloc::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op) {
+  ATRACE_CALL();
+  ATRACE_INT("operation id", op);
+  struct ion_flush_data flush_data;
+  int err = 0;
+
+  flush_data.handle = handle;
+  flush_data.vaddr = base;
+  // offset and length are unsigned int
+  flush_data.offset = offset;
+  flush_data.length = size;
+
+  struct ion_custom_data d;
+  switch (op) {
+    case CACHE_CLEAN:
+      d.cmd = ION_IOC_CLEAN_CACHES;
+      break;
+    case CACHE_INVALIDATE:
+      d.cmd = ION_IOC_INV_CACHES;
+      break;
+    case CACHE_CLEAN_AND_INVALIDATE:
+    default:
+      d.cmd = ION_IOC_CLEAN_INV_CACHES;
+  }
+
+  d.arg = (unsigned long)(&flush_data);  // NOLINT
+  if (ioctl(ion_dev_fd_, INT(ION_IOC_CUSTOM), &d)) {
+    err = -errno;
+    ALOGE("%s: ION_IOC_CLEAN_INV_CACHES failed with error - %s", __FUNCTION__, strerror(errno));
+    return err;
+  }
+
+  return 0;
+}
+
+}  // namespace gralloc1
diff --git a/sdm845/libgralloc1/gr_ion_alloc.h b/sdm845/libgralloc1/gr_ion_alloc.h
new file mode 100644
index 0000000..b25f509
--- /dev/null
+++ b/sdm845/libgralloc1/gr_ion_alloc.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2011-2017, 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 __GR_ION_ALLOC_H__
+#define __GR_ION_ALLOC_H__
+
+#include <linux/msm_ion.h>
+
+#define FD_INIT -1
+
+namespace gralloc1 {
+
+enum {
+  CACHE_CLEAN = 0x1,
+  CACHE_INVALIDATE,
+  CACHE_CLEAN_AND_INVALIDATE,
+};
+
+struct AllocData {
+  void *base = NULL;
+  int fd = -1;
+  int ion_handle = -1;
+  unsigned int offset = 0;
+  unsigned int size = 0;
+  unsigned int align = 1;
+  uintptr_t handle = 0;
+  bool uncached = false;
+  unsigned int flags = 0x0;
+  unsigned int heap_id = 0x0;
+  unsigned int alloc_type = 0x0;
+};
+
+class IonAlloc {
+ public:
+  IonAlloc() { ion_dev_fd_ = FD_INIT; }
+
+  ~IonAlloc() { CloseIonDevice(); }
+
+  bool Init();
+  int AllocBuffer(AllocData *data);
+  int FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd, int ion_handle);
+  int MapBuffer(void **base, unsigned int size, unsigned int offset, int fd);
+  int ImportBuffer(int fd);
+  int UnmapBuffer(void *base, unsigned int size, unsigned int offset);
+  int CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op);
+
+ private:
+  const char *kIonDevice = "/dev/ion";
+
+  int OpenIonDevice();
+  void CloseIonDevice();
+
+  int ion_dev_fd_;
+};
+
+}  // namespace gralloc1
+
+#endif  // __GR_ION_ALLOC_H__
diff --git a/sdm845/libgralloc1/gr_priv_handle.h b/sdm845/libgralloc1/gr_priv_handle.h
new file mode 100644
index 0000000..49e09a5
--- /dev/null
+++ b/sdm845/libgralloc1/gr_priv_handle.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __GR_PRIV_HANDLE_H__
+#define __GR_PRIV_HANDLE_H__
+
+#include <cutils/log.h>
+#include <hardware/gralloc1.h>
+#include <hardware/gralloc.h>
+#include <cinttypes>
+
+#define GRALLOC1_FUNCTION_PERFORM 0x00001000
+
+#define DBG_HANDLE false
+
+typedef gralloc1_error_t (*GRALLOC1_PFN_PERFORM)(gralloc1_device_t *device, int operation, ...);
+
+#define PRIV_HANDLE_CONST(exp) static_cast<const private_handle_t *>(exp)
+
+struct private_handle_t : public native_handle_t {
+  enum {
+    PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
+    PRIV_FLAGS_USES_ION = 0x00000008,
+    PRIV_FLAGS_NEEDS_FLUSH = 0x00000020,
+    PRIV_FLAGS_INTERNAL_ONLY = 0x00000040,
+    PRIV_FLAGS_NON_CPU_WRITER = 0x00000080,
+    PRIV_FLAGS_CACHED = 0x00000200,
+    PRIV_FLAGS_SECURE_BUFFER = 0x00000400,
+    PRIV_FLAGS_EXTERNAL_ONLY = 0x00002000,
+    PRIV_FLAGS_PROTECTED_BUFFER = 0x00004000,
+    PRIV_FLAGS_VIDEO_ENCODER = 0x00010000,
+    PRIV_FLAGS_CAMERA_WRITE = 0x00020000,
+    PRIV_FLAGS_CAMERA_READ = 0x00040000,
+    PRIV_FLAGS_HW_COMPOSER = 0x00080000,
+    PRIV_FLAGS_HW_TEXTURE = 0x00100000,
+    PRIV_FLAGS_ITU_R_601 = 0x00200000,     // Unused from display
+    PRIV_FLAGS_ITU_R_601_FR = 0x00400000,  // Unused from display
+    PRIV_FLAGS_ITU_R_709 = 0x00800000,     // Unused from display
+    PRIV_FLAGS_SECURE_DISPLAY = 0x01000000,
+    PRIV_FLAGS_TILE_RENDERED = 0x02000000,
+    PRIV_FLAGS_CPU_RENDERED = 0x04000000,
+    PRIV_FLAGS_UBWC_ALIGNED = 0x08000000,
+    PRIV_FLAGS_DISP_CONSUMER = 0x10000000,
+    PRIV_FLAGS_CLIENT_ALLOCATED = 0x20000000,   // Ion buffer allocated outside of gralloc
+  };
+
+  // file-descriptors dup'd over IPC
+  int fd;
+  int fd_metadata;
+
+  // values sent over IPC
+  int magic;
+  int flags;
+  int width;        // holds width of the actual buffer allocated
+  int height;       // holds height of the  actual buffer allocated
+  int unaligned_width;   // holds width client asked to allocate
+  int unaligned_height;  // holds height client asked to allocate
+  int format;
+  int buffer_type;
+  unsigned int size;
+  unsigned int offset;
+  unsigned int offset_metadata;
+  uint64_t base                            __attribute__((aligned(8)));
+  uint64_t base_metadata                   __attribute__((aligned(8)));
+  uint64_t gpuaddr                         __attribute__((aligned(8)));
+  uint64_t id                              __attribute__((aligned(8)));
+  gralloc1_producer_usage_t producer_usage __attribute__((aligned(8)));
+  gralloc1_consumer_usage_t consumer_usage __attribute__((aligned(8)));
+  unsigned int layer_count;
+
+  static const int kNumFds = 2;
+  static const int kMagic = 'gmsm';
+
+  static inline int NumInts() {
+    return ((sizeof(private_handle_t) - sizeof(native_handle_t)) / sizeof(int))
+        - kNumFds;
+  }
+
+  private_handle_t(int fd,
+                   int meta_fd,
+                   int flags,
+                   int width,
+                   int height,
+                   int uw,
+                   int uh,
+                   int format,
+                   int buf_type,
+                   unsigned int size,
+                   gralloc1_producer_usage_t prod_usage = GRALLOC1_PRODUCER_USAGE_NONE,
+                   gralloc1_consumer_usage_t cons_usage = GRALLOC1_CONSUMER_USAGE_NONE)
+      : fd(fd),
+        fd_metadata(meta_fd),
+        magic(kMagic),
+        flags(flags),
+        width(width),
+        height(height),
+        unaligned_width(uw),
+        unaligned_height(uh),
+        format(format),
+        buffer_type(buf_type),
+        size(size),
+        offset(0),
+        offset_metadata(0),
+        base(0),
+        base_metadata(0),
+        gpuaddr(0),
+        id(0),
+        producer_usage(prod_usage),
+        consumer_usage(cons_usage),
+        layer_count(1) {
+    version = static_cast<int>(sizeof(native_handle));
+    numInts = NumInts();
+    numFds = kNumFds;
+  }
+
+// Legacy constructor used by some clients
+  private_handle_t(int fd, unsigned int size, int usage, int buf_type, int format, int w, int h)
+  : private_handle_t(fd, -1, PRIV_FLAGS_CLIENT_ALLOCATED, w, h, 0, 0, format, buf_type, size,
+                     static_cast<gralloc1_producer_usage_t>(usage),
+                     static_cast<gralloc1_consumer_usage_t>(usage)) {
+  }
+
+  ~private_handle_t() {
+    magic = 0;
+    ALOGE_IF(DBG_HANDLE, "Deleting buffer handle %p", this);
+  }
+
+  static int validate(const native_handle *h) {
+    const private_handle_t *hnd = (const private_handle_t *)h;
+    if (!h || h->version != sizeof(native_handle) || h->numInts != NumInts() ||
+        h->numFds != kNumFds || hnd->magic != kMagic) {
+      ALOGE(
+          "Invalid gralloc handle (at %p): ver(%d/%zu) ints(%d/%d) fds(%d/%d) "
+          "magic(%c%c%c%c/%c%c%c%c)",
+          h, h ? h->version : -1, sizeof(native_handle), h ? h->numInts : -1, NumInts(),
+          h ? h->numFds : -1, kNumFds,
+          hnd ? (((hnd->magic >> 24) & 0xFF) ? ((hnd->magic >> 24) & 0xFF) : '-') : '?',
+          hnd ? (((hnd->magic >> 16) & 0xFF) ? ((hnd->magic >> 16) & 0xFF) : '-') : '?',
+          hnd ? (((hnd->magic >> 8) & 0xFF) ? ((hnd->magic >> 8) & 0xFF) : '-') : '?',
+          hnd ? (((hnd->magic >> 0) & 0xFF) ? ((hnd->magic >> 0) & 0xFF) : '-') : '?',
+          (kMagic >> 24) & 0xFF, (kMagic >> 16) & 0xFF, (kMagic >> 8) & 0xFF, (kMagic >> 0) & 0xFF);
+      return -EINVAL;
+    }
+
+    return 0;
+  }
+
+  static void Dump(const private_handle_t *hnd) {
+    ALOGD("handle id:%" PRIu64 " wxh:%dx%d uwxuh:%dx%d size: %d fd:%d fd_meta:%d flags:0x%x "
+          "prod_usage:0x%" PRIx64" cons_usage:0x%" PRIx64 " format:0x%x layer_count: %d",
+          hnd->id, hnd->width, hnd->height, hnd->unaligned_width, hnd->unaligned_height, hnd->size,
+          hnd->fd, hnd->fd_metadata, hnd->flags, hnd->producer_usage, hnd->consumer_usage,
+          hnd->format, hnd->layer_count);
+  }
+
+  int GetUnalignedWidth() const { return unaligned_width; }
+
+  int GetUnalignedHeight() const { return unaligned_height; }
+
+  int GetColorFormat() const { return format; }
+
+  unsigned int GetLayerCount() const { return layer_count; }
+
+  int GetStride() const {
+    // In handle we currently store aligned width after allocation.
+    return width;
+  }
+
+  gralloc1_consumer_usage_t GetConsumerUsage() const { return consumer_usage; }
+
+  gralloc1_producer_usage_t GetProducerUsage() const { return producer_usage; }
+
+  uint64_t GetBackingstore() const { return id; }
+};
+
+#endif  // __GR_PRIV_HANDLE_H__
diff --git a/sdm845/libgralloc1/gr_utils.cpp b/sdm845/libgralloc1/gr_utils.cpp
new file mode 100644
index 0000000..b3056e1
--- /dev/null
+++ b/sdm845/libgralloc1/gr_utils.cpp
@@ -0,0 +1,841 @@
+/*
+ * Copyright (c) 2011-2017, 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 <media/msm_media_info.h>
+#include <algorithm>
+
+#include "gr_utils.h"
+#include "gr_adreno_info.h"
+#include "qdMetaData.h"
+
+#define ASTC_BLOCK_SIZE 16
+
+#ifndef COLOR_FMT_P010_UBWC
+#define COLOR_FMT_P010_UBWC 9
+#endif
+
+namespace gralloc1 {
+
+bool IsUncompressedRGBFormat(int format) {
+  switch (format) {
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+    case HAL_PIXEL_FORMAT_RGB_888:
+    case HAL_PIXEL_FORMAT_RGB_565:
+    case HAL_PIXEL_FORMAT_BGR_565:
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+    case HAL_PIXEL_FORMAT_RGBA_5551:
+    case HAL_PIXEL_FORMAT_RGBA_4444:
+    case HAL_PIXEL_FORMAT_R_8:
+    case HAL_PIXEL_FORMAT_RG_88:
+    case HAL_PIXEL_FORMAT_BGRX_8888:
+    case HAL_PIXEL_FORMAT_RGBA_1010102:
+    case HAL_PIXEL_FORMAT_ARGB_2101010:
+    case HAL_PIXEL_FORMAT_RGBX_1010102:
+    case HAL_PIXEL_FORMAT_XRGB_2101010:
+    case HAL_PIXEL_FORMAT_BGRA_1010102:
+    case HAL_PIXEL_FORMAT_ABGR_2101010:
+    case HAL_PIXEL_FORMAT_BGRX_1010102:
+    case HAL_PIXEL_FORMAT_XBGR_2101010:
+    case HAL_PIXEL_FORMAT_RGBA_FP16:
+    case HAL_PIXEL_FORMAT_BGR_888:
+      return true;
+    default:
+      break;
+  }
+
+  return false;
+}
+
+bool IsCompressedRGBFormat(int format) {
+  switch (format) {
+    case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR:
+    case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+      return true;
+    default:
+      break;
+  }
+
+  return false;
+}
+
+uint32_t GetBppForUncompressedRGB(int format) {
+  uint32_t bpp = 0;
+  switch (format) {
+    case HAL_PIXEL_FORMAT_RGBA_FP16:
+      bpp = 8;
+      break;
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+    case HAL_PIXEL_FORMAT_BGRX_8888:
+    case HAL_PIXEL_FORMAT_RGBA_1010102:
+    case HAL_PIXEL_FORMAT_ARGB_2101010:
+    case HAL_PIXEL_FORMAT_RGBX_1010102:
+    case HAL_PIXEL_FORMAT_XRGB_2101010:
+    case HAL_PIXEL_FORMAT_BGRA_1010102:
+    case HAL_PIXEL_FORMAT_ABGR_2101010:
+    case HAL_PIXEL_FORMAT_BGRX_1010102:
+    case HAL_PIXEL_FORMAT_XBGR_2101010:
+      bpp = 4;
+      break;
+    case HAL_PIXEL_FORMAT_RGB_888:
+    case HAL_PIXEL_FORMAT_BGR_888:
+      bpp = 3;
+      break;
+    case HAL_PIXEL_FORMAT_RGB_565:
+    case HAL_PIXEL_FORMAT_BGR_565:
+    case HAL_PIXEL_FORMAT_RGBA_5551:
+    case HAL_PIXEL_FORMAT_RGBA_4444:
+      bpp = 2;
+      break;
+    default:
+      ALOGE("Error : %s New format request = 0x%x", __FUNCTION__, format);
+      break;
+  }
+
+  return bpp;
+}
+
+bool CpuCanAccess(gralloc1_producer_usage_t prod_usage, gralloc1_consumer_usage_t cons_usage) {
+  return CpuCanRead(prod_usage, cons_usage) || CpuCanWrite(prod_usage);
+}
+
+bool CpuCanRead(gralloc1_producer_usage_t prod_usage, gralloc1_consumer_usage_t cons_usage) {
+  if (prod_usage & GRALLOC1_PRODUCER_USAGE_CPU_READ) {
+    return true;
+  }
+
+  if (cons_usage & GRALLOC1_CONSUMER_USAGE_CPU_READ) {
+    return true;
+  }
+
+  return false;
+}
+
+bool CpuCanWrite(gralloc1_producer_usage_t prod_usage) {
+  if (prod_usage & GRALLOC1_PRODUCER_USAGE_CPU_WRITE) {
+    // Application intends to use CPU for rendering
+    return true;
+  }
+
+  return false;
+}
+
+unsigned int GetSize(const BufferInfo &info, unsigned int alignedw,
+                     unsigned int alignedh) {
+  unsigned int size = 0;
+  int format = info.format;
+  int width = info.width;
+  int height = info.height;
+  gralloc1_producer_usage_t prod_usage = info.prod_usage;
+  gralloc1_consumer_usage_t cons_usage = info.cons_usage;
+
+  if (IsUBwcEnabled(format, prod_usage, cons_usage)) {
+    return GetUBwcSize(width, height, format, alignedw, alignedh);
+  }
+
+  if (IsUncompressedRGBFormat(format)) {
+    uint32_t bpp = GetBppForUncompressedRGB(format);
+    size = alignedw * alignedh * bpp;
+    return size;
+  }
+
+  if (IsCompressedRGBFormat(format)) {
+    size = alignedw * alignedh * ASTC_BLOCK_SIZE;
+    return size;
+  }
+
+  // Below switch should be for only YUV/custom formats
+  switch (format) {
+    case HAL_PIXEL_FORMAT_RAW16:
+    case HAL_PIXEL_FORMAT_Y16:
+      size = alignedw * alignedh * 2;
+      break;
+    case HAL_PIXEL_FORMAT_RAW10:
+    case HAL_PIXEL_FORMAT_RAW12:
+      size = ALIGN(alignedw * alignedh, SIZE_4K);
+      break;
+    case HAL_PIXEL_FORMAT_RAW8:
+    case HAL_PIXEL_FORMAT_Y8:
+      size = alignedw * alignedh * 1;
+      break;
+
+      // adreno formats
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:  // NV21
+      size = ALIGN(alignedw * alignedh, SIZE_4K);
+      size += (unsigned int)ALIGN(2 * ALIGN(width / 2, 32) * ALIGN(height / 2, 32), SIZE_4K);
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:  // NV12
+      // The chroma plane is subsampled,
+      // but the pitch in bytes is unchanged
+      // The GPU needs 4K alignment, but the video decoder needs 8K
+      size = ALIGN(alignedw * alignedh, SIZE_8K);
+      size += ALIGN(alignedw * (unsigned int)ALIGN(height / 2, 32), SIZE_8K);
+      break;
+    case HAL_PIXEL_FORMAT_YV12:
+      if ((format == HAL_PIXEL_FORMAT_YV12) && ((width & 1) || (height & 1))) {
+        ALOGE("w or h is odd for the YV12 format");
+        return 0;
+      }
+      size = alignedw * alignedh + (ALIGN(alignedw / 2, 16) * (alignedh / 2)) * 2;
+      size = ALIGN(size, (unsigned int)SIZE_4K);
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+      size = ALIGN((alignedw * alignedh) + (alignedw * alignedh) / 2 + 1, SIZE_4K);
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+      size = ALIGN((alignedw * alignedh * 2) + (alignedw * alignedh) + 1, SIZE_4K);
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+    case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+    case HAL_PIXEL_FORMAT_YCbCr_422_I:
+    case HAL_PIXEL_FORMAT_YCrCb_422_I:
+    case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+      if (width & 1) {
+        ALOGE("width is odd for the YUV422_SP format");
+        return 0;
+      }
+      size = ALIGN(alignedw * alignedh * 2, SIZE_4K);
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+      size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
+      break;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+      size = VENUS_BUFFER_SIZE(COLOR_FMT_NV21, width, height);
+      break;
+    case HAL_PIXEL_FORMAT_BLOB:
+    case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+      if (height != 1) {
+        ALOGE("%s: Buffers with HAL_PIXEL_FORMAT_BLOB must have height 1 ", __FUNCTION__);
+        return 0;
+      }
+      size = (unsigned int)width;
+      break;
+    case HAL_PIXEL_FORMAT_NV21_ZSL:
+      size = ALIGN((alignedw * alignedh) + (alignedw * alignedh) / 2, SIZE_4K);
+      break;
+    default:
+      ALOGE("%s: Unrecognized pixel format: 0x%x", __FUNCTION__, format);
+      return 0;
+  }
+
+  return size;
+}
+
+void GetBufferSizeAndDimensions(const BufferInfo &info, unsigned int *size,
+                                unsigned int *alignedw, unsigned int *alignedh) {
+  GetAlignedWidthAndHeight(info, alignedw, alignedh);
+  *size = GetSize(info, *alignedw, *alignedh);
+}
+
+void GetYuvUbwcSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height,
+                           int color_format, struct android_ycbcr *ycbcr) {
+  // UBWC buffer has these 4 planes in the following sequence:
+  // Y_Meta_Plane, Y_Plane, UV_Meta_Plane, UV_Plane
+  unsigned int y_meta_stride, y_meta_height, y_meta_size;
+  unsigned int y_stride, y_height, y_size;
+  unsigned int c_meta_stride, c_meta_height, c_meta_size;
+  unsigned int alignment = 4096;
+
+  y_meta_stride = VENUS_Y_META_STRIDE(color_format, INT(width));
+  y_meta_height = VENUS_Y_META_SCANLINES(color_format, INT(height));
+  y_meta_size = ALIGN((y_meta_stride * y_meta_height), alignment);
+
+  y_stride = VENUS_Y_STRIDE(color_format, INT(width));
+  y_height = VENUS_Y_SCANLINES(color_format, INT(height));
+  y_size = ALIGN((y_stride * y_height), alignment);
+
+  c_meta_stride = VENUS_UV_META_STRIDE(color_format, INT(width));
+  c_meta_height = VENUS_UV_META_SCANLINES(color_format, INT(height));
+  c_meta_size = ALIGN((c_meta_stride * c_meta_height), alignment);
+
+  ycbcr->y = reinterpret_cast<void *>(base + y_meta_size);
+  ycbcr->cb = reinterpret_cast<void *>(base + y_meta_size + y_size + c_meta_size);
+  ycbcr->cr = reinterpret_cast<void *>(base + y_meta_size + y_size + c_meta_size + 1);
+  ycbcr->ystride = y_stride;
+  ycbcr->cstride = VENUS_UV_STRIDE(color_format, INT(width));
+}
+
+void GetYuvUbwcInterlacedSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height,
+                                     int color_format, struct android_ycbcr *ycbcr) {
+  unsigned int uv_stride, uv_height, uv_size;
+  unsigned int alignment = 4096;
+  uint64_t field_base;
+
+  // UBWC interlaced has top-bottom field layout with each field as
+  // 4-plane NV12_UBWC with width = image_width & height = image_height / 2.
+  // Client passed ycbcr argument is ptr to struct android_ycbcr[2].
+  // Plane info to be filled for each field separately.
+  height = (height + 1) >> 1;
+  uv_stride = VENUS_UV_STRIDE(color_format, INT(width));
+  uv_height = VENUS_UV_SCANLINES(color_format, INT(height));
+  uv_size = ALIGN((uv_stride * uv_height), alignment);
+
+  field_base = base;
+  GetYuvUbwcSPPlaneInfo(field_base, width, height, COLOR_FMT_NV12_UBWC, &ycbcr[0]);
+
+  field_base = reinterpret_cast<uint64_t>(ycbcr[0].cb) + uv_size;
+  GetYuvUbwcSPPlaneInfo(field_base, width, height, COLOR_FMT_NV12_UBWC, &ycbcr[1]);
+}
+
+void GetYuvSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height, uint32_t bpp,
+                       struct android_ycbcr *ycbcr) {
+  unsigned int ystride, cstride;
+
+  ystride = cstride = UINT(width) * bpp;
+  ycbcr->y = reinterpret_cast<void *>(base);
+  ycbcr->cb = reinterpret_cast<void *>(base + ystride * UINT(height));
+  ycbcr->cr = reinterpret_cast<void *>(base + ystride * UINT(height) + 1);
+  ycbcr->ystride = ystride;
+  ycbcr->cstride = cstride;
+  ycbcr->chroma_step = 2 * bpp;
+}
+
+int GetYUVPlaneInfo(const private_handle_t *hnd, struct android_ycbcr *ycbcr) {
+  int err = 0;
+  uint32_t width = UINT(hnd->width);
+  uint32_t height = UINT(hnd->height);
+  int format = hnd->format;
+  gralloc1_producer_usage_t prod_usage = hnd->GetProducerUsage();
+  gralloc1_consumer_usage_t cons_usage = hnd->GetConsumerUsage();
+  unsigned int ystride, cstride;
+  bool interlaced = false;
+
+  memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+  MetaData_t *metadata = reinterpret_cast<MetaData_t *>(hnd->base_metadata);
+
+  // Check if UBWC buffer has been rendered in linear format.
+  if (metadata && (metadata->operation & LINEAR_FORMAT)) {
+    format = INT(metadata->linearFormat);
+  }
+
+  // Check metadata if the geometry has been updated.
+  if (metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+    int usage = 0;
+
+    if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+      usage = GRALLOC1_PRODUCER_USAGE_PRIVATE_ALLOC_UBWC;
+    }
+
+    BufferInfo info(metadata->bufferDim.sliceWidth, metadata->bufferDim.sliceHeight, format,
+                    prod_usage, cons_usage);
+    GetAlignedWidthAndHeight(info, &width, &height);
+  }
+
+  // Check metadata for interlaced content.
+  if (metadata && (metadata->operation & PP_PARAM_INTERLACED)) {
+    interlaced = metadata->interlaced ? true : false;
+  }
+
+  // Get the chroma offsets from the handle width/height. We take advantage
+  // of the fact the width _is_ the stride
+  switch (format) {
+    // Semiplanar
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+      // Same as YCbCr_420_SP_VENUS
+      GetYuvSPPlaneInfo(hnd->base, width, height, 1, ycbcr);
+      break;
+
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+      GetYuvSPPlaneInfo(hnd->base, width, height, 2, ycbcr);
+      break;
+
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+      if (!interlaced) {
+        GetYuvUbwcSPPlaneInfo(hnd->base, width, height, COLOR_FMT_NV12_UBWC, ycbcr);
+      } else {
+        GetYuvUbwcInterlacedSPPlaneInfo(hnd->base, width, height, COLOR_FMT_NV12_UBWC, ycbcr);
+      }
+      ycbcr->chroma_step = 2;
+      break;
+
+    case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+      GetYuvUbwcSPPlaneInfo(hnd->base, width, height, COLOR_FMT_NV12_BPP10_UBWC, ycbcr);
+      ycbcr->chroma_step = 3;
+      break;
+
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+      GetYuvUbwcSPPlaneInfo(hnd->base, width, height, COLOR_FMT_P010_UBWC, ycbcr);
+      ycbcr->chroma_step = 4;
+      break;
+
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+    case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_NV21_ZSL:
+    case HAL_PIXEL_FORMAT_RAW16:
+    case HAL_PIXEL_FORMAT_Y16:
+    case HAL_PIXEL_FORMAT_RAW10:
+    case HAL_PIXEL_FORMAT_RAW8:
+    case HAL_PIXEL_FORMAT_Y8:
+      GetYuvSPPlaneInfo(hnd->base, width, height, 1, ycbcr);
+      std::swap(ycbcr->cb, ycbcr->cr);
+      break;
+
+      // Planar
+    case HAL_PIXEL_FORMAT_YV12:
+      ystride = width;
+      cstride = ALIGN(width / 2, 16);
+      ycbcr->y = reinterpret_cast<void *>(hnd->base);
+      ycbcr->cr = reinterpret_cast<void *>(hnd->base + ystride * height);
+      ycbcr->cb = reinterpret_cast<void *>(hnd->base + ystride * height + cstride * height / 2);
+      ycbcr->ystride = ystride;
+      ycbcr->cstride = cstride;
+      ycbcr->chroma_step = 1;
+      break;
+    case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+      ystride = width * 2;
+      cstride = 0;
+      ycbcr->y  = reinterpret_cast<void *>(hnd->base);
+      ycbcr->cr = NULL;
+      ycbcr->cb = NULL;
+      ycbcr->ystride = ystride;
+      ycbcr->cstride = 0;
+      ycbcr->chroma_step = 0;
+      break;
+      // Unsupported formats
+    case HAL_PIXEL_FORMAT_YCbCr_422_I:
+    case HAL_PIXEL_FORMAT_YCrCb_422_I:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+    default:
+      ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__, format);
+      err = -EINVAL;
+  }
+
+  return err;
+}
+
+// Explicitly defined UBWC formats
+bool IsUBwcFormat(int format) {
+  switch (format) {
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+    case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool IsUBwcSupported(int format) {
+  // Existing HAL formats with UBWC support
+  switch (format) {
+    case HAL_PIXEL_FORMAT_BGR_565:
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_RGBA_1010102:
+    case HAL_PIXEL_FORMAT_RGBX_1010102:
+      return true;
+    default:
+      break;
+  }
+
+  return false;
+}
+
+bool IsUBwcEnabled(int format, gralloc1_producer_usage_t prod_usage,
+                   gralloc1_consumer_usage_t cons_usage) {
+  // Allow UBWC, if client is using an explicitly defined UBWC pixel format.
+  if (IsUBwcFormat(format)) {
+    return true;
+  }
+
+  // Allow UBWC, if an OpenGL client sets UBWC usage flag and GPU plus MDP
+  // support the format. OR if a non-OpenGL client like Rotator, sets UBWC
+  // usage flag and MDP supports the format.
+  if ((prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_ALLOC_UBWC) && IsUBwcSupported(format)) {
+    bool enable = true;
+    // Query GPU for UBWC only if buffer is intended to be used by GPU.
+    if ((cons_usage & GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE) ||
+        (prod_usage & GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET)) {
+      enable = AdrenoMemInfo::GetInstance()->IsUBWCSupportedByGPU(format);
+    }
+
+    // Allow UBWC, only if CPU usage flags are not set
+    if (enable && !(CpuCanAccess(prod_usage, cons_usage))) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void GetYuvUBwcWidthAndHeight(int width, int height, int format, unsigned int *aligned_w,
+                              unsigned int *aligned_h) {
+  switch (format) {
+    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+      *aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, width);
+      *aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, height);
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+      // The macro returns the stride which is 4/3 times the width, hence * 3/4
+      *aligned_w = (VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, width) * 3) / 4;
+      *aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, height);
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+      // The macro returns the stride which is 2 times the width, hence / 2
+      *aligned_w = (VENUS_Y_STRIDE(COLOR_FMT_P010_UBWC, width) / 2);
+      *aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_P010_UBWC, height);
+      break;
+    default:
+      ALOGE("%s: Unsupported pixel format: 0x%x", __FUNCTION__, format);
+      *aligned_w = 0;
+      *aligned_h = 0;
+      break;
+  }
+}
+
+void GetRgbUBwcBlockSize(uint32_t bpp, int *block_width, int *block_height) {
+  *block_width = 0;
+  *block_height = 0;
+
+  switch (bpp) {
+    case 2:
+    case 4:
+      *block_width = 16;
+      *block_height = 4;
+      break;
+    case 8:
+      *block_width = 8;
+      *block_height = 4;
+      break;
+    case 16:
+      *block_width = 4;
+      *block_height = 4;
+      break;
+    default:
+      ALOGE("%s: Unsupported bpp: %d", __FUNCTION__, bpp);
+      break;
+  }
+}
+
+unsigned int GetRgbUBwcMetaBufferSize(int width, int height, uint32_t bpp) {
+  unsigned int size = 0;
+  int meta_width, meta_height;
+  int block_width, block_height;
+
+  GetRgbUBwcBlockSize(bpp, &block_width, &block_height);
+  if (!block_width || !block_height) {
+    ALOGE("%s: Unsupported bpp: %d", __FUNCTION__, bpp);
+    return size;
+  }
+
+  // Align meta buffer height to 16 blocks
+  meta_height = ALIGN(((height + block_height - 1) / block_height), 16);
+
+  // Align meta buffer width to 64 blocks
+  meta_width = ALIGN(((width + block_width - 1) / block_width), 64);
+
+  // Align meta buffer size to 4K
+  size = (unsigned int)ALIGN((meta_width * meta_height), 4096);
+
+  return size;
+}
+
+unsigned int GetUBwcSize(int width, int height, int format, unsigned int alignedw,
+                         unsigned int alignedh) {
+  unsigned int size = 0;
+  uint32_t bpp = 0;
+  switch (format) {
+    case HAL_PIXEL_FORMAT_BGR_565:
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+    case HAL_PIXEL_FORMAT_RGBA_1010102:
+    case HAL_PIXEL_FORMAT_RGBX_1010102:
+      bpp = GetBppForUncompressedRGB(format);
+      size = alignedw * alignedh * bpp;
+      size += GetRgbUBwcMetaBufferSize(width, height, bpp);
+      break;
+    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+      size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, width, height);
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+      size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_BPP10_UBWC, width, height);
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+      size = VENUS_BUFFER_SIZE(COLOR_FMT_P010_UBWC, width, height);
+      break;
+    default:
+      ALOGE("%s: Unsupported pixel format: 0x%x", __FUNCTION__, format);
+      break;
+  }
+
+  return size;
+}
+
+int GetRgbDataAddress(private_handle_t *hnd, void **rgb_data) {
+  int err = 0;
+
+  // This api is for RGB* formats
+  if (!gralloc1::IsUncompressedRGBFormat(hnd->format)) {
+    return -EINVAL;
+  }
+
+  // linear buffer, nothing to do further
+  if (!(hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED)) {
+    *rgb_data = reinterpret_cast<void *>(hnd->base);
+    return err;
+  }
+
+  unsigned int meta_size = 0;
+  uint32_t bpp = GetBppForUncompressedRGB(hnd->format);
+  switch (hnd->format) {
+    case HAL_PIXEL_FORMAT_BGR_565:
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+    case HAL_PIXEL_FORMAT_RGBA_1010102:
+    case HAL_PIXEL_FORMAT_RGBX_1010102:
+      meta_size = GetRgbUBwcMetaBufferSize(hnd->width, hnd->height, bpp);
+      break;
+    default:
+      ALOGE("%s:Unsupported RGB format: 0x%x", __FUNCTION__, hnd->format);
+      err = -EINVAL;
+      break;
+  }
+  *rgb_data = reinterpret_cast<void *>(hnd->base + meta_size);
+
+  return err;
+}
+
+void GetAlignedWidthAndHeight(const BufferInfo &info, unsigned int *alignedw,
+                              unsigned int *alignedh) {
+  int width = info.width;
+  int height = info.height;
+  int format = info.format;
+  gralloc1_producer_usage_t prod_usage = info.prod_usage;
+  gralloc1_consumer_usage_t cons_usage = info.cons_usage;
+
+  // Currently surface padding is only computed for RGB* surfaces.
+  bool ubwc_enabled = IsUBwcEnabled(format, prod_usage, cons_usage);
+  int tile = ubwc_enabled;
+
+  if (IsUncompressedRGBFormat(format)) {
+    AdrenoMemInfo::GetInstance()->AlignUnCompressedRGB(width, height, format, tile, alignedw,
+                                                       alignedh);
+    return;
+  }
+
+  if (ubwc_enabled) {
+    GetYuvUBwcWidthAndHeight(width, height, format, alignedw, alignedh);
+    return;
+  }
+
+  if (IsCompressedRGBFormat(format)) {
+    AdrenoMemInfo::GetInstance()->AlignCompressedRGB(width, height, format, alignedw, alignedh);
+    return;
+  }
+
+  int aligned_w = width;
+  int aligned_h = height;
+  unsigned int alignment = 32;
+
+  // Below should be only YUV family
+  switch (format) {
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+      alignment = AdrenoMemInfo::GetInstance()->GetGpuPixelAlignment();
+      aligned_w = ALIGN(width, alignment);
+      break;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+      aligned_w = ALIGN(width, alignment);
+      break;
+    case HAL_PIXEL_FORMAT_RAW16:
+    case HAL_PIXEL_FORMAT_Y16:
+    case HAL_PIXEL_FORMAT_Y8:
+      aligned_w = ALIGN(width, 16);
+      break;
+    case HAL_PIXEL_FORMAT_RAW12:
+      aligned_w = ALIGN(width * 12 / 8, 8);
+      break;
+    case HAL_PIXEL_FORMAT_RAW10:
+      aligned_w = ALIGN(width * 10 / 8, 8);
+      break;
+    case HAL_PIXEL_FORMAT_RAW8:
+      aligned_w = ALIGN(width, 8);
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+      aligned_w = ALIGN(width, 128);
+      break;
+    case HAL_PIXEL_FORMAT_YV12:
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+    case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+    case HAL_PIXEL_FORMAT_YCbCr_422_I:
+    case HAL_PIXEL_FORMAT_YCrCb_422_I:
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+      aligned_w = ALIGN(width, 16);
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+      aligned_w = INT(VENUS_Y_STRIDE(COLOR_FMT_NV12, width));
+      aligned_h = INT(VENUS_Y_SCANLINES(COLOR_FMT_NV12, height));
+      break;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+      aligned_w = INT(VENUS_Y_STRIDE(COLOR_FMT_NV21, width));
+      aligned_h = INT(VENUS_Y_SCANLINES(COLOR_FMT_NV21, height));
+      break;
+    case HAL_PIXEL_FORMAT_BLOB:
+    case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+      break;
+    case HAL_PIXEL_FORMAT_NV21_ZSL:
+      aligned_w = ALIGN(width, 64);
+      aligned_h = ALIGN(height, 64);
+      break;
+    default:
+      break;
+  }
+
+  *alignedw = (unsigned int)aligned_w;
+  *alignedh = (unsigned int)aligned_h;
+}
+
+int GetBufferLayout(private_handle_t *hnd, uint32_t stride[4],
+                    uint32_t offset[4], uint32_t *num_planes) {
+  if (!hnd || !stride || !offset || !num_planes) {
+    return -EINVAL;
+  }
+
+  struct android_ycbcr yuvInfo = {};
+  *num_planes = 1;
+  stride[0] = 0;
+
+  switch (hnd->format) {
+    case HAL_PIXEL_FORMAT_RGB_565:
+    case HAL_PIXEL_FORMAT_BGR_565:
+    case HAL_PIXEL_FORMAT_RGBA_5551:
+    case HAL_PIXEL_FORMAT_RGBA_4444:
+      stride[0] = static_cast<uint32_t>(hnd->width * 2);
+      break;
+    case HAL_PIXEL_FORMAT_RGB_888:
+      stride[0] = static_cast<uint32_t>(hnd->width * 3);
+      break;
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+    case HAL_PIXEL_FORMAT_BGRX_8888:
+    case HAL_PIXEL_FORMAT_RGBA_1010102:
+    case HAL_PIXEL_FORMAT_ARGB_2101010:
+    case HAL_PIXEL_FORMAT_RGBX_1010102:
+    case HAL_PIXEL_FORMAT_XRGB_2101010:
+    case HAL_PIXEL_FORMAT_BGRA_1010102:
+    case HAL_PIXEL_FORMAT_ABGR_2101010:
+    case HAL_PIXEL_FORMAT_BGRX_1010102:
+    case HAL_PIXEL_FORMAT_XBGR_2101010:
+      stride[0] = static_cast<uint32_t>(hnd->width * 4);
+      break;
+  }
+
+  // Format is RGB
+  if (stride[0]) {
+    return 0;
+  }
+
+  (*num_planes)++;
+  int ret = GetYUVPlaneInfo(hnd, &yuvInfo);
+  if (ret < 0) {
+    ALOGE("%s failed", __FUNCTION__);
+    return ret;
+  }
+
+  stride[0] = static_cast<uint32_t>(yuvInfo.ystride);
+  offset[0] = static_cast<uint32_t>(reinterpret_cast<uint64_t>(yuvInfo.y) - hnd->base);
+  stride[1] = static_cast<uint32_t>(yuvInfo.cstride);
+  switch (hnd->format) {
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+    case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+      offset[1] = static_cast<uint32_t>(reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base);
+      break;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+      offset[1] = static_cast<uint32_t>(reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base);
+      break;
+    case HAL_PIXEL_FORMAT_YV12:
+      offset[1] = static_cast<uint32_t>(reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base);
+      stride[2] = static_cast<uint32_t>(yuvInfo.cstride);
+      offset[2] = static_cast<uint32_t>(reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base);
+      (*num_planes)++;
+      break;
+    default:
+      ALOGW("%s: Unsupported format", __FUNCTION__);
+      ret = -EINVAL;
+  }
+
+  if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+    std::fill(offset, offset + 4, 0);
+  }
+
+  return 0;
+}
+
+}  // namespace gralloc1
diff --git a/sdm845/libgralloc1/gr_utils.h b/sdm845/libgralloc1/gr_utils.h
new file mode 100644
index 0000000..2a08539
--- /dev/null
+++ b/sdm845/libgralloc1/gr_utils.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GR_UTILS_H__
+#define __GR_UTILS_H__
+
+#include "gralloc_priv.h"
+
+#define SZ_2M 0x200000
+#define SZ_1M 0x100000
+#define SZ_4K 0x1000
+
+#define SIZE_4K 4096
+#define SIZE_8K 4096
+
+#define INT(exp) static_cast<int>(exp)
+#define UINT(exp) static_cast<unsigned int>(exp)
+
+namespace gralloc1 {
+
+struct BufferInfo {
+  BufferInfo(int w, int h, int f, gralloc1_producer_usage_t prod = GRALLOC1_PRODUCER_USAGE_NONE,
+             gralloc1_consumer_usage_t cons = GRALLOC1_CONSUMER_USAGE_NONE) : width(w), height(h),
+    format(f), prod_usage(prod), cons_usage(cons) {}
+  int width;
+  int height;
+  int format;
+  gralloc1_producer_usage_t prod_usage;
+  gralloc1_consumer_usage_t cons_usage;
+};
+
+template <class Type1, class Type2>
+inline Type1 ALIGN(Type1 x, Type2 align) {
+  return (Type1)((x + (Type1)align - 1) & ~((Type1)align - 1));
+}
+
+bool IsCompressedRGBFormat(int format);
+bool IsUncompressedRGBFormat(int format);
+uint32_t GetBppForUncompressedRGB(int format);
+bool CpuCanAccess(gralloc1_producer_usage_t prod_usage, gralloc1_consumer_usage_t cons_usage);
+bool CpuCanRead(gralloc1_producer_usage_t prod_usage, gralloc1_consumer_usage_t cons_usage);
+bool CpuCanWrite(gralloc1_producer_usage_t prod_usage);
+unsigned int GetSize(const BufferInfo &d, unsigned int alignedw, unsigned int alignedh);
+void GetBufferSizeAndDimensions(const BufferInfo &d, unsigned int *size,
+                                unsigned int *alignedw, unsigned int *alignedh);
+void GetAlignedWidthAndHeight(const BufferInfo &d, unsigned int *aligned_w,
+                              unsigned int *aligned_h);
+int GetYUVPlaneInfo(const private_handle_t *hnd, struct android_ycbcr *ycbcr);
+int GetRgbDataAddress(private_handle_t *hnd, void **rgb_data);
+bool IsUBwcFormat(int format);
+bool IsUBwcSupported(int format);
+bool IsUBwcEnabled(int format, gralloc1_producer_usage_t prod_usage,
+                   gralloc1_consumer_usage_t cons_usage);
+void GetYuvUBwcWidthAndHeight(int width, int height, int format, unsigned int *aligned_w,
+                              unsigned int *aligned_h);
+void GetYuvSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height, uint32_t bpp,
+                       struct android_ycbcr *ycbcr);
+void GetYuvUbwcSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height, int color_format,
+                           struct android_ycbcr *ycbcr);
+void GetYuvUbwcInterlacedSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height,
+                                     int color_format, struct android_ycbcr *ycbcr);
+void GetRgbUBwcBlockSize(uint32_t bpp, int *block_width, int *block_height);
+unsigned int GetRgbUBwcMetaBufferSize(int width, int height, uint32_t bpp);
+unsigned int GetUBwcSize(int width, int height, int format, unsigned int alignedw,
+                         unsigned int alignedh);
+int GetBufferLayout(private_handle_t *hnd, uint32_t stride[4],
+                    uint32_t offset[4], uint32_t *num_planes);
+}  // namespace gralloc1
+
+#endif  // __GR_UTILS_H__
diff --git a/sdm845/libgralloc1/gralloc_priv.h b/sdm845/libgralloc1/gralloc_priv.h
new file mode 100644
index 0000000..1839d2f
--- /dev/null
+++ b/sdm845/libgralloc1/gralloc_priv.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __GRALLOC_PRIV_H__
+#define __GRALLOC_PRIV_H__
+
+#include <unistd.h>
+#include "gr_priv_handle.h"
+
+#define ROUND_UP_PAGESIZE(x) roundUpToPageSize(x)
+inline int roundUpToPageSize(int x) {
+    return (x + (getpagesize()-1)) & ~(getpagesize()-1);
+}
+
+/* Gralloc usage bits indicating the type of allocation that should be used */
+/* Refer gralloc1_producer_usage_t & gralloc1_consumer_usage-t in gralloc1.h */
+
+/* Producer flags */
+/* Non linear, Universal Bandwidth Compression */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_ALLOC_UBWC  GRALLOC1_PRODUCER_USAGE_PRIVATE_0
+
+/* Set this for allocating uncached memory (using O_DSYNC),
+ * cannot be used with noncontiguous heaps */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_UNCACHED    GRALLOC1_PRODUCER_USAGE_PRIVATE_1
+
+/* CAMERA heap is a carveout heap for camera, is not secured */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_CAMERA_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_2
+
+/* ADSP heap is a carveout heap, is not secured */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_ADSP_HEAP   GRALLOC1_PRODUCER_USAGE_PRIVATE_3
+
+/* IOMMU heap comes from manually allocated pages, can be cached/uncached, is not secured */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_IOMMU_HEAP  GRALLOC1_PRODUCER_USAGE_PRIVATE_4
+
+/* MM heap is a carveout heap for video, can be secured */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_MM_HEAP     GRALLOC1_PRODUCER_USAGE_PRIVATE_5
+
+/* Use legacy ZSL definition until we know the correct usage on gralloc1 */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_CAMERA_ZSL  GRALLOC_USAGE_HW_CAMERA_ZSL
+
+
+/* Consumer flags */
+/* TODO(user): Fix when producer and consumer flags are actually separated */
+/* This flag is set for WFD usecase */
+#define GRALLOC1_CONSUMER_USAGE_PRIVATE_WFD            0x00200000
+
+/* This flag is used for SECURE display usecase */
+#define GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY 0x00800000
+
+/* Buffer content should be displayed on a primary display only */
+#define GRALLOC1_CONSUMER_USAGE_PRIVATE_INTERNAL_ONLY  0x04000000
+
+/* Buffer content should be displayed on an external display only */
+#define GRALLOC1_CONSUMER_USAGE_PRIVATE_EXTERNAL_ONLY  0x08000000
+
+
+/* Legacy gralloc0.x definitions */
+/* Some clients may still be using the old flags */
+#define GRALLOC_USAGE_PRIVATE_ALLOC_UBWC GRALLOC1_PRODUCER_USAGE_PRIVATE_ALLOC_UBWC
+#define GRALLOC_USAGE_PRIVATE_UNCACHED GRALLOC1_PRODUCER_USAGE_PRIVATE_UNCACHED
+#define GRALLOC_USAGE_PRIVATE_IOMMU_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_IOMMU_HEAP
+#define GRALLOC_USAGE_PRIVATE_WFD GRALLOC1_CONSUMER_USAGE_PRIVATE_WFD
+#define GRALLOC_USAGE_PRIVATE_CAMERA_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_CAMERA_HEAP
+#define GRALLOC_USAGE_PRIVATE_MM_HEAP 0x0
+
+
+
+// for PERFORM API :
+#define GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER 1
+#define GRALLOC_MODULE_PERFORM_GET_STRIDE 2
+#define GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE 3
+#define GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE 4
+#define GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES 5
+#define GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE 6
+#define GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO 7
+#define GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO 8
+#define GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG 9
+#define GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS 10
+#define GRALLOC_MODULE_PERFORM_GET_IGC 11
+#define GRALLOC_MODULE_PERFORM_SET_IGC 12
+#define GRALLOC_MODULE_PERFORM_SET_SINGLE_BUFFER_MODE 13
+#define GRALLOC1_MODULE_PERFORM_GET_BUFFER_SIZE_AND_DIMENSIONS 14
+#define GRALLOC1_MODULE_PERFORM_ALLOCATE_BUFFER 15
+#define GRALLOC1_MODULE_PERFORM_GET_INTERLACE_FLAG 16
+
+// OEM specific HAL formats
+#define HAL_PIXEL_FORMAT_RGBA_5551 6
+#define HAL_PIXEL_FORMAT_RGBA_4444 7
+#define HAL_PIXEL_FORMAT_NV12_ENCODEABLE 0x102
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS 0x7FA30C04
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED 0x7FA30C03
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP 0x109
+#define HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO 0x7FA30C01
+#define HAL_PIXEL_FORMAT_YCrCb_422_SP 0x10B
+#define HAL_PIXEL_FORMAT_R_8 0x10D
+#define HAL_PIXEL_FORMAT_RG_88 0x10E
+#define HAL_PIXEL_FORMAT_YCbCr_444_SP 0x10F
+#define HAL_PIXEL_FORMAT_YCrCb_444_SP 0x110
+#define HAL_PIXEL_FORMAT_YCrCb_422_I 0x111
+#define HAL_PIXEL_FORMAT_BGRX_8888 0x112
+#define HAL_PIXEL_FORMAT_NV21_ZSL 0x113
+#define HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS 0x114
+#define HAL_PIXEL_FORMAT_BGR_565 0x115
+#define HAL_PIXEL_FORMAT_RAW8 0x123
+
+// 10 bit
+#define HAL_PIXEL_FORMAT_ARGB_2101010 0x117
+#define HAL_PIXEL_FORMAT_RGBX_1010102 0x118
+#define HAL_PIXEL_FORMAT_XRGB_2101010 0x119
+#define HAL_PIXEL_FORMAT_BGRA_1010102 0x11A
+#define HAL_PIXEL_FORMAT_ABGR_2101010 0x11B
+#define HAL_PIXEL_FORMAT_BGRX_1010102 0x11C
+#define HAL_PIXEL_FORMAT_XBGR_2101010 0x11D
+#define HAL_PIXEL_FORMAT_YCbCr_420_P010 0x11F
+#define HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC 0x124
+
+#define HAL_PIXEL_FORMAT_CbYCrY_422_I            0x120
+#define HAL_PIXEL_FORMAT_BGR_888                 0x121
+
+#define HAL_PIXEL_FORMAT_INTERLACE 0x180
+
+// v4l2_fourcc('Y', 'U', 'Y', 'L'). 24 bpp YUYV 4:2:2 10 bit per component
+#define HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT 0x4C595559
+
+// v4l2_fourcc('Y', 'B', 'W', 'C'). 10 bit per component. This compressed
+// format reduces the memory access bandwidth
+#define HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT_COMPRESSED 0x43574259
+
+// UBWC aligned Venus format
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC 0x7FA30C06
+#define HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC     0x7FA30C09
+
+// Khronos ASTC formats
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+
+/* possible values for inverse gamma correction */
+#define HAL_IGC_NOT_SPECIFIED 0
+#define HAL_IGC_s_RGB 1
+
+/* Color Space: Values maps to ColorSpace_t in qdMetadata.h */
+#define HAL_CSC_ITU_R_601         0
+#define HAL_CSC_ITU_R_601_FR      1
+#define HAL_CSC_ITU_R_709         2
+#define HAL_CSC_ITU_R_2020        3
+#define HAL_CSC_ITU_R_2020_FR     4
+
+/* possible formats for 3D content*/
+enum {
+  HAL_NO_3D = 0x0,
+  HAL_3D_SIDE_BY_SIDE_L_R = 0x1,
+  HAL_3D_SIDE_BY_SIDE_R_L = 0x2,
+  HAL_3D_TOP_BOTTOM = 0x4,
+  HAL_3D_IN_SIDE_BY_SIDE_L_R = 0x10000,  // unused legacy format
+};
+
+enum { BUFFER_TYPE_UI = 0, BUFFER_TYPE_VIDEO };
+
+#endif  // __GRALLOC_PRIV_H__
diff --git a/sdm845/liblight/Android.mk b/sdm845/liblight/Android.mk
new file mode 100644
index 0000000..2f2e1ca
--- /dev/null
+++ b/sdm845/liblight/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+# HAL module implemenation stored in
+# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.board.platform>.so
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/common/inc
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/qdcm/inc
+
+LOCAL_SRC_FILES := lights.c lights_prv.cpp
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SHARED_LIBRARIES := liblog libcutils libsdm-disp-vndapis
+LOCAL_CFLAGS := -DLOG_TAG=\"qdlights\"
+LOCAL_CLANG  := true
+LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_TAGS := optional
+LOCAL_VENDOR_MODULE := true
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/sdm845/liblight/NOTICE b/sdm845/liblight/NOTICE
new file mode 100644
index 0000000..7340b9e
--- /dev/null
+++ b/sdm845/liblight/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2008, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/sdm845/liblight/lights.c b/sdm845/liblight/lights.c
new file mode 100644
index 0000000..3b5068c
--- /dev/null
+++ b/sdm845/liblight/lights.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2014, 2017 The  Linux Foundation. All rights reserved.
+ * Not a contribution
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+// #define LOG_NDEBUG 0
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <hardware/lights.h>
+#include "lights_prv.h"
+
+#ifndef DEFAULT_LOW_PERSISTENCE_MODE_BRIGHTNESS
+#define DEFAULT_LOW_PERSISTENCE_MODE_BRIGHTNESS 0x80
+#endif
+
+/******************************************************************************/
+
+static pthread_once_t g_init = PTHREAD_ONCE_INIT;
+static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
+static struct light_state_t g_notification;
+static struct light_state_t g_battery;
+static int g_last_backlight_mode = BRIGHTNESS_MODE_USER;
+static int g_attention = 0;
+static int g_brightness_max = 0;
+
+char const*const RED_LED_FILE
+        = "/sys/class/leds/red/brightness";
+
+char const*const GREEN_LED_FILE
+        = "/sys/class/leds/green/brightness";
+
+char const*const BLUE_LED_FILE
+        = "/sys/class/leds/blue/brightness";
+
+char const*const LCD_FILE
+        = "/sys/class/leds/lcd-backlight/brightness";
+
+char const*const LCD_FILE2
+        = "/sys/class/backlight/panel0-backlight/brightness";
+
+char const*const BUTTON_FILE
+        = "/sys/class/leds/button-backlight/brightness";
+
+char const*const RED_BLINK_FILE
+        = "/sys/class/leds/red/blink";
+
+char const*const GREEN_BLINK_FILE
+        = "/sys/class/leds/green/blink";
+
+char const*const BLUE_BLINK_FILE
+        = "/sys/class/leds/blue/blink";
+
+char const*const PERSISTENCE_FILE
+        = "/sys/class/graphics/fb0/msm_fb_persist_mode";
+
+/**
+ * device methods
+ */
+
+void init_globals(void)
+{
+    // init the mutex
+    pthread_mutex_init(&g_lock, NULL);
+}
+
+static int
+write_int(char const* path, int value)
+{
+    int fd;
+    static int already_warned = 0;
+
+    fd = open(path, O_RDWR);
+    if (fd >= 0) {
+        char buffer[20];
+        int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);
+        ssize_t amt = write(fd, buffer, (size_t)bytes);
+        close(fd);
+        return amt == -1 ? -errno : 0;
+    } else {
+        if (already_warned == 0) {
+            ALOGE("write_int failed to open %s\n", path);
+            already_warned = 1;
+        }
+        return -errno;
+    }
+}
+
+static int
+is_lit(struct light_state_t const* state)
+{
+    return state->color & 0x00ffffff;
+}
+
+static int
+rgb_to_brightness(struct light_state_t const* state)
+{
+    int color = state->color & 0x00ffffff;
+    return ((77*((color>>16)&0x00ff))
+            + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
+}
+
+static int
+set_light_backlight(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    int err = 0;
+    int brightness = rgb_to_brightness(state);
+    unsigned int lpEnabled =
+        state->brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE;
+    if(!dev) {
+        return -1;
+    }
+
+    pthread_mutex_lock(&g_lock);
+    // Toggle low persistence mode state
+    if ((g_last_backlight_mode != state->brightnessMode && lpEnabled) ||
+        (!lpEnabled &&
+         g_last_backlight_mode == BRIGHTNESS_MODE_LOW_PERSISTENCE)) {
+        if ((err = write_int(PERSISTENCE_FILE, lpEnabled)) != 0) {
+            ALOGE("%s: Failed to write to %s: %s\n", __FUNCTION__,
+                   PERSISTENCE_FILE, strerror(errno));
+        }
+        if (lpEnabled != 0) {
+            brightness = DEFAULT_LOW_PERSISTENCE_MODE_BRIGHTNESS;
+        }
+    }
+
+    g_last_backlight_mode = state->brightnessMode;
+
+    if (!err) {
+        if (!access(LCD_FILE, F_OK)) {
+            err = write_int(LCD_FILE, brightness);
+        } else {
+            err = write_int(LCD_FILE2, brightness);
+        }
+    }
+
+    pthread_mutex_unlock(&g_lock);
+    return err;
+}
+
+static int
+set_light_backlight_ext(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    int err = 0;
+
+    if(!dev) {
+        return -1;
+    }
+
+    int brightness = state->color & 0x00ffffff;
+    pthread_mutex_lock(&g_lock);
+
+    if (brightness >= 0 && brightness <= g_brightness_max) {
+        set_brightness_ext_level(brightness);
+    }
+
+    pthread_mutex_unlock(&g_lock);
+
+    return err;
+}
+
+static int
+set_speaker_light_locked(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    int red, green, blue;
+    int blink;
+    int onMS, offMS;
+    unsigned int colorRGB;
+
+    if(!dev) {
+        return -1;
+    }
+
+    switch (state->flashMode) {
+        case LIGHT_FLASH_TIMED:
+            onMS = state->flashOnMS;
+            offMS = state->flashOffMS;
+            break;
+        case LIGHT_FLASH_NONE:
+        default:
+            onMS = 0;
+            offMS = 0;
+            break;
+    }
+
+    colorRGB = state->color;
+
+#if 0
+    ALOGD("set_speaker_light_locked mode %d, colorRGB=%08X, onMS=%d, offMS=%d\n",
+            state->flashMode, colorRGB, onMS, offMS);
+#endif
+
+    red = (colorRGB >> 16) & 0xFF;
+    green = (colorRGB >> 8) & 0xFF;
+    blue = colorRGB & 0xFF;
+
+    if (onMS > 0 && offMS > 0) {
+        /*
+         * if ON time == OFF time
+         *   use blink mode 2
+         * else
+         *   use blink mode 1
+         */
+        if (onMS == offMS)
+            blink = 2;
+        else
+            blink = 1;
+    } else {
+        blink = 0;
+    }
+
+    if (blink) {
+        if (red) {
+            if (write_int(RED_BLINK_FILE, blink))
+                write_int(RED_LED_FILE, 0);
+    }
+        if (green) {
+            if (write_int(GREEN_BLINK_FILE, blink))
+                write_int(GREEN_LED_FILE, 0);
+    }
+        if (blue) {
+            if (write_int(BLUE_BLINK_FILE, blink))
+                write_int(BLUE_LED_FILE, 0);
+    }
+    } else {
+        write_int(RED_LED_FILE, red);
+        write_int(GREEN_LED_FILE, green);
+        write_int(BLUE_LED_FILE, blue);
+    }
+
+    return 0;
+}
+
+static void
+handle_speaker_battery_locked(struct light_device_t* dev)
+{
+    if (is_lit(&g_battery)) {
+        set_speaker_light_locked(dev, &g_battery);
+    } else {
+        set_speaker_light_locked(dev, &g_notification);
+    }
+}
+
+static int
+set_light_battery(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    pthread_mutex_lock(&g_lock);
+    g_battery = *state;
+    handle_speaker_battery_locked(dev);
+    pthread_mutex_unlock(&g_lock);
+    return 0;
+}
+
+static int
+set_light_notifications(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    pthread_mutex_lock(&g_lock);
+    g_notification = *state;
+    handle_speaker_battery_locked(dev);
+    pthread_mutex_unlock(&g_lock);
+    return 0;
+}
+
+static int
+set_light_attention(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    pthread_mutex_lock(&g_lock);
+    if (state->flashMode == LIGHT_FLASH_HARDWARE) {
+        g_attention = state->flashOnMS;
+    } else if (state->flashMode == LIGHT_FLASH_NONE) {
+        g_attention = 0;
+    }
+    handle_speaker_battery_locked(dev);
+    pthread_mutex_unlock(&g_lock);
+    return 0;
+}
+
+static int
+set_light_buttons(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    int err = 0;
+    if(!dev) {
+        return -1;
+    }
+    pthread_mutex_lock(&g_lock);
+    err = write_int(BUTTON_FILE, state->color & 0xFF);
+    pthread_mutex_unlock(&g_lock);
+    return err;
+}
+
+/** Close the lights device */
+static int
+close_lights(struct light_device_t *dev)
+{
+    if (dev) {
+        free(dev);
+    }
+    return 0;
+}
+
+
+/******************************************************************************/
+
+/**
+ * module methods
+ */
+
+/** Open a new instance of a lights device using name */
+static int open_lights(const struct hw_module_t* module, char const* name,
+        struct hw_device_t** device)
+{
+    int (*set_light)(struct light_device_t* dev,
+            struct light_state_t const* state);
+
+    if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {
+        char property[PROPERTY_VALUE_MAX];
+        property_get("persist.extend.brightness", property, "0");
+
+        if(!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
+           !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
+            property_get("persist.display.max_brightness", property, "255");
+            g_brightness_max = atoi(property);
+            set_brightness_ext_init();
+            set_light = set_light_backlight_ext;
+        } else
+            set_light = set_light_backlight;
+    } else if (0 == strcmp(LIGHT_ID_BATTERY, name))
+        set_light = set_light_battery;
+    else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
+        set_light = set_light_notifications;
+    else if (0 == strcmp(LIGHT_ID_BUTTONS, name))
+        set_light = set_light_buttons;
+    else if (0 == strcmp(LIGHT_ID_ATTENTION, name))
+        set_light = set_light_attention;
+    else
+        return -EINVAL;
+
+    pthread_once(&g_init, init_globals);
+
+    struct light_device_t *dev = malloc(sizeof(struct light_device_t));
+
+    if(!dev)
+        return -ENOMEM;
+
+    memset(dev, 0, sizeof(*dev));
+
+    dev->common.tag = HARDWARE_DEVICE_TAG;
+    dev->common.version = LIGHTS_DEVICE_API_VERSION_2_0;
+    dev->common.module = (struct hw_module_t*)module;
+    dev->common.close = (int (*)(struct hw_device_t*))close_lights;
+    dev->set_light = set_light;
+
+    *device = (struct hw_device_t*)dev;
+    return 0;
+}
+
+static struct hw_module_methods_t lights_module_methods = {
+    .open =  open_lights,
+};
+
+/*
+ * The lights Module
+ */
+struct hw_module_t HAL_MODULE_INFO_SYM = {
+    .tag = HARDWARE_MODULE_TAG,
+    .version_major = 1,
+    .version_minor = 0,
+    .id = LIGHTS_HARDWARE_MODULE_ID,
+    .name = "lights Module",
+    .author = "Google, Inc.",
+    .methods = &lights_module_methods,
+};
diff --git a/sdm845/liblight/lights_prv.cpp b/sdm845/liblight/lights_prv.cpp
new file mode 100644
index 0000000..f916ed2
--- /dev/null
+++ b/sdm845/liblight/lights_prv.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, 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 <hardware/hwcomposer_defs.h>
+#include "disp_color_apis.h"
+#include "lights_prv.h"
+
+/******************************************************************************/
+static DISPAPI_HANDLE g_ctx;
+
+/**
+ * device methods
+ */
+
+void set_brightness_ext_init(void)
+{
+   disp_api_init((DISPAPI_HANDLE*) &g_ctx, 0);
+}
+
+int set_brightness_ext_level(int level)
+{
+    int err = disp_api_set_panel_brightness_level_ext(g_ctx, HWC_DISPLAY_PRIMARY,
+                                                 level, 0);
+
+    return err;
+}
diff --git a/sdm845/liblight/lights_prv.h b/sdm845/liblight/lights_prv.h
new file mode 100644
index 0000000..e0ec736
--- /dev/null
+++ b/sdm845/liblight/lights_prv.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017, 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 LIGHTS_PRV_H
+#define LIGHTS_PRV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void set_brightness_ext_init(void);
+extern int set_brightness_ext_level(int level);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/sdm845/libmemtrack/Android.mk b/sdm845/libmemtrack/Android.mk
new file mode 100644
index 0000000..d4014bb
--- /dev/null
+++ b/sdm845/libmemtrack/Android.mk
@@ -0,0 +1,29 @@
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+# HAL module implemenation stored in
+# hw/<POWERS_HARDWARE_MODULE_ID>.<ro.hardware>.so
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_VENDOR_MODULE := true
+LOCAL_C_INCLUDES += hardware/libhardware/include
+LOCAL_CFLAGS := -Wconversion -Wall -Werror -Wno-sign-conversion
+LOCAL_CLANG  := true
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SRC_FILES := memtrack_msm.c kgsl.c
+LOCAL_MODULE := memtrack.$(TARGET_BOARD_PLATFORM)
+include $(BUILD_SHARED_LIBRARY)
diff --git a/sdm845/libmemtrack/kgsl.c b/sdm845/libmemtrack/kgsl.c
new file mode 100644
index 0000000..69ee901
--- /dev/null
+++ b/sdm845/libmemtrack/kgsl.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <hardware/memtrack.h>
+
+#include "memtrack_msm.h"
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+#define min(x, y) ((x) < (y) ? (x) : (y))
+
+struct memtrack_record record_templates[] = {
+    {
+        .flags = MEMTRACK_FLAG_SMAPS_ACCOUNTED |
+                 MEMTRACK_FLAG_PRIVATE |
+                 MEMTRACK_FLAG_NONSECURE,
+    },
+    {
+        .flags = MEMTRACK_FLAG_SMAPS_UNACCOUNTED |
+                 MEMTRACK_FLAG_PRIVATE |
+                 MEMTRACK_FLAG_NONSECURE,
+    },
+};
+
+int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type,
+                             struct memtrack_record *records,
+                             size_t *num_records)
+{
+    size_t allocated_records = min(*num_records, ARRAY_SIZE(record_templates));
+    FILE *fp;
+    char line[1024];
+    char tmp[128];
+    size_t accounted_size = 0;
+    size_t unaccounted_size = 0;
+
+    *num_records = ARRAY_SIZE(record_templates);
+
+    /* fastpath to return the necessary number of records */
+    if (allocated_records == 0) {
+        return 0;
+    }
+
+    memcpy(records, record_templates,
+           sizeof(struct memtrack_record) * allocated_records);
+
+    snprintf(tmp, sizeof(tmp), "/d/kgsl/proc/%d/mem", pid);
+    fp = fopen(tmp, "r");
+    if (fp == NULL) {
+        return -errno;
+    }
+
+    /* Go through each line of <pid>/mem file and for every entry of type "gpumem"
+     * check if the gpubuffer entry is usermapped or not. If the entry is usermapped
+     * count the entry as accounted else count the entry as unaccounted.
+     */
+    while (1) {
+        unsigned long size, mapsize;
+        char line_type[7];
+        char flags[10];
+        char line_usage[19];
+        int ret, egl_surface_count = 0, egl_image_count = 0;
+
+        if (fgets(line, sizeof(line), fp) == NULL) {
+            break;
+        }
+
+        /* Format:
+         *  gpuaddr useraddr     size    id flags       type            usage sglen mapsize eglsrf eglimg
+         * 545ba000 545ba000     4096     1 -----pY     gpumem      arraybuffer     1  4096      0      0
+         */
+        ret = sscanf(line, "%*x %*x %lu %*d %9s %6s %18s %*d %lu %6d %6d\n",
+                       &size, flags, line_type, line_usage, &mapsize,
+                       &egl_surface_count, &egl_image_count);
+        if (ret != 7) {
+            continue;
+        }
+
+        if (size == 0) {
+            fclose(fp);
+            return -EINVAL;
+        }
+
+        if (unaccounted_size + size < size) {
+            fclose(fp);
+            return -ERANGE;
+        }
+
+        if (type == MEMTRACK_TYPE_GL && strcmp(line_type, "gpumem") == 0) {
+
+            if (flags[6] == 'Y') {
+                if (accounted_size + mapsize < accounted_size) {
+                    fclose(fp);
+                    return -ERANGE;
+                }
+
+                accounted_size += mapsize;
+
+                if (mapsize > size) {
+                    fclose(fp);
+                    return -EINVAL;
+                }
+                unaccounted_size += size - mapsize;
+            } else {
+                unaccounted_size += size;
+            }
+        } else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, "ion") == 0) {
+            if (strcmp(line_usage, "egl_surface") == 0) {
+                unaccounted_size += size;
+            }
+            else if (egl_surface_count == 0) {
+                unaccounted_size += size / (egl_image_count ? egl_image_count : 1);
+            }
+        }
+    }
+
+    if (allocated_records > 0) {
+        records[0].size_in_bytes = accounted_size;
+    }
+    if (allocated_records > 1) {
+        records[1].size_in_bytes = unaccounted_size;
+    }
+
+    fclose(fp);
+
+    return 0;
+}
diff --git a/sdm845/libmemtrack/memtrack_msm.c b/sdm845/libmemtrack/memtrack_msm.c
new file mode 100644
index 0000000..e369d5f
--- /dev/null
+++ b/sdm845/libmemtrack/memtrack_msm.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+
+#include <hardware/memtrack.h>
+
+#include "memtrack_msm.h"
+
+int msm_memtrack_init(const struct memtrack_module *module)
+{
+    if(!module)
+        return -1;
+    return 0;
+}
+
+int msm_memtrack_get_memory(const struct memtrack_module *module,
+                                pid_t pid,
+                                int type,
+                                struct memtrack_record *records,
+                                size_t *num_records)
+{
+    if(!module)
+        return -1;
+    if (type == MEMTRACK_TYPE_GL || type == MEMTRACK_TYPE_GRAPHICS) {
+        return kgsl_memtrack_get_memory(pid, type, records, num_records);
+    }
+
+    return -EINVAL;
+}
+
+static struct hw_module_methods_t memtrack_module_methods = {
+    .open = NULL,
+};
+
+struct memtrack_module HAL_MODULE_INFO_SYM = {
+    .common = {
+        .tag = HARDWARE_MODULE_TAG,
+        .module_api_version = MEMTRACK_MODULE_API_VERSION_0_1,
+        .hal_api_version = HARDWARE_HAL_API_VERSION,
+        .id = MEMTRACK_HARDWARE_MODULE_ID,
+        .name = "MSM Memory Tracker HAL",
+        .author = "The Android Open Source Project",
+        .methods = &memtrack_module_methods,
+    },
+
+    .init = msm_memtrack_init,
+    .getMemory = msm_memtrack_get_memory,
+};
+
diff --git a/sdm845/libmemtrack/memtrack_msm.h b/sdm845/libmemtrack/memtrack_msm.h
new file mode 100644
index 0000000..74aa576
--- /dev/null
+++ b/sdm845/libmemtrack/memtrack_msm.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MEMTRACK_MSM_H_
+#define _MEMTRACK_MSM_H_
+
+int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type,
+                             struct memtrack_record *records,
+                             size_t *num_records);
+
+#endif
diff --git a/sdm845/libqdutils/Android.mk b/sdm845/libqdutils/Android.mk
new file mode 100644
index 0000000..60efb3a
--- /dev/null
+++ b/sdm845/libqdutils/Android.mk
@@ -0,0 +1,51 @@
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := libqdutils
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_TAGS             := optional
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libbinder libqservice
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_HEADER_LIBRARIES        := display_headers
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdutils\" -Wno-sign-conversion
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
+LOCAL_COPY_HEADERS            := display_config.h qd_utils.h
+LOCAL_SRC_FILES               := profiler.cpp \
+                                 qd_utils.cpp \
+                                 display_config.cpp
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_COPY_HEADERS_TO           := $(common_header_export_path)
+LOCAL_COPY_HEADERS              := qdMetaData.h qd_utils.h
+LOCAL_SHARED_LIBRARIES          := liblog libcutils
+LOCAL_C_INCLUDES                := $(common_includes)
+LOCAL_HEADER_LIBRARIES          := display_headers
+LOCAL_ADDITIONAL_DEPENDENCIES   := $(common_deps)
+LOCAL_SRC_FILES                 := qdMetaData.cpp qd_utils.cpp
+LOCAL_CFLAGS                    := $(common_flags) -Wno-sign-conversion
+LOCAL_CFLAGS                    += -DLOG_TAG=\"DisplayMetaData\"
+
+LOCAL_MODULE_TAGS               := optional
+LOCAL_MODULE                    := libqdMetaData
+LOCAL_VENDOR_MODULE             := true
+include $(BUILD_SHARED_LIBRARY)
+
+
+include $(CLEAR_VARS)
+
+LOCAL_SHARED_LIBRARIES          := liblog libcutils
+LOCAL_C_INCLUDES                := $(common_includes)
+LOCAL_HEADER_LIBRARIES          := display_headers
+LOCAL_ADDITIONAL_DEPENDENCIES   := $(common_deps)
+LOCAL_SRC_FILES                 := qdMetaData.cpp qd_utils.cpp
+LOCAL_CFLAGS                    := $(common_flags) -Wno-sign-conversion
+LOCAL_CFLAGS                    += -DLOG_TAG=\"DisplayMetaData\"
+
+LOCAL_MODULE_TAGS               := optional
+LOCAL_MODULE                    := libqdMetaData.system
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/sdm845/libqdutils/Makefile.am b/sdm845/libqdutils/Makefile.am
new file mode 100644
index 0000000..01fbf19
--- /dev/null
+++ b/sdm845/libqdutils/Makefile.am
@@ -0,0 +1,32 @@
+h_sources = qdMetaData.h
+
+cpp_sources = qdMetaData.cpp
+
+library_includedir = $(includedir)
+library_include_HEADERS = $(h_sources)
+
+lib_LTLIBRARIES = libqdMetaData.la
+libqdMetaData_la_CC = @CC@
+libqdMetaData_la_SOURCES = $(cpp_sources)
+libqdMetaData_la_CFLAGS = $(AM_CFLAGS) -DLOG_TAG=\"DisplayMetaData\"
+libqdMetaData_la_CPPFLAGS = $(AM_CPPFLAGS)
+libqdMetaData_LDADD = -lcutils -llog
+libqdMetaData_la_LDFLAGS = -shared -avoid-version
+
+header_sources = display_config.h
+
+c_sources = profiler.cpp \
+            qd_utils.cpp \
+            display_config.cpp
+
+library_includedir = $(includedir)
+library_include_HEADERS = $(header_sources)
+
+lib_LTLIBRARIES += libqdutils.la
+libqdutils_la_CC = @CC@
+libqdutils_la_SOURCES = $(c_sources)
+libqdutils_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"qdutils\"
+libqdutils_la_CPPFLAGS = $(AM_CPPFLAGS)
+libqdutils_LDADD = -lhardware -lcutils -llog -lbinder
+libqdutils_la_LIBADD = ../libqservice/libqservice.la
+libqdutils_la_LDFLAGS = -shared -avoid-version
\ No newline at end of file
diff --git a/sdm845/libqdutils/display_config.cpp b/sdm845/libqdutils/display_config.cpp
new file mode 100644
index 0000000..83d912e
--- /dev/null
+++ b/sdm845/libqdutils/display_config.cpp
@@ -0,0 +1,368 @@
+/*
+* Copyright (c) 2013-2014, 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*    * Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above
+*      copyright notice, this list of conditions and the following
+*      disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation. nor the names of its
+*      contributors may be used to endorse or promote products derived
+*      from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <display_config.h>
+#include <QServiceUtils.h>
+#include <qd_utils.h>
+
+using namespace android;
+using namespace qService;
+
+namespace qdutils {
+
+//=============================================================================
+// The functions below run in the client process and wherever necessary
+// do a binder call to HWC to get/set data.
+
+int isExternalConnected(void) {
+    int ret;
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::CHECK_EXTERNAL_STATUS,
+                &inParcel , &outParcel);
+    }
+    if(err) {
+        ALOGE("%s: Failed to get external status err=%d", __FUNCTION__, err);
+        ret = err;
+    } else {
+        ret = outParcel.readInt32();
+    }
+    return ret;
+}
+
+int getDisplayAttributes(int dpy, DisplayAttributes_t& dpyattr) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(dpy);
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::GET_DISPLAY_ATTRIBUTES,
+                &inParcel, &outParcel);
+    }
+    if(!err) {
+        dpyattr.vsync_period = outParcel.readInt32();
+        dpyattr.xres = outParcel.readInt32();
+        dpyattr.yres = outParcel.readInt32();
+        dpyattr.xdpi = outParcel.readFloat();
+        dpyattr.ydpi = outParcel.readFloat();
+        dpyattr.panel_type = outParcel.readInt32();
+    } else {
+        ALOGE("%s() failed with err %d", __FUNCTION__, err);
+    }
+    return err;
+}
+
+int setHSIC(int dpy, const HSICData_t& hsic_data) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(dpy);
+    inParcel.writeInt32(hsic_data.hue);
+    inParcel.writeFloat(hsic_data.saturation);
+    inParcel.writeInt32(hsic_data.intensity);
+    inParcel.writeFloat(hsic_data.contrast);
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::SET_HSIC_DATA, &inParcel, &outParcel);
+    }
+    if(err)
+        ALOGE("%s: Failed to get external status err=%d", __FUNCTION__, err);
+    return err;
+}
+
+int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(dpy);
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::GET_DISPLAY_VISIBLE_REGION,
+                &inParcel, &outParcel);
+    }
+    if(!err) {
+        rect.left = outParcel.readInt32();
+        rect.top = outParcel.readInt32();
+        rect.right = outParcel.readInt32();
+        rect.bottom = outParcel.readInt32();
+    } else {
+        ALOGE("%s: Failed to getVisibleRegion for dpy =%d: err = %d",
+              __FUNCTION__, dpy, err);
+    }
+    return err;
+}
+
+int setViewFrame(int dpy, int l, int t, int r, int b) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(dpy);
+    inParcel.writeInt32(l);
+    inParcel.writeInt32(t);
+    inParcel.writeInt32(r);
+    inParcel.writeInt32(b);
+
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::SET_VIEW_FRAME,
+                &inParcel, &outParcel);
+    }
+    if(err)
+        ALOGE("%s: Failed to set view frame for dpy %d err=%d",
+                            __FUNCTION__, dpy, err);
+
+    return err;
+}
+
+int setSecondaryDisplayStatus(int dpy, uint32_t status) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(dpy);
+    inParcel.writeInt32(status);
+
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::SET_SECONDARY_DISPLAY_STATUS,
+                &inParcel, &outParcel);
+    }
+    if(err)
+        ALOGE("%s: Failed for dpy %d status = %d err=%d", __FUNCTION__, dpy,
+                                                        status, err);
+
+    return err;
+}
+
+int configureDynRefreshRate(uint32_t op, uint32_t refreshRate) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(op);
+    inParcel.writeInt32(refreshRate);
+
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::CONFIGURE_DYN_REFRESH_RATE,
+                               &inParcel, &outParcel);
+    }
+
+    if(err)
+        ALOGE("%s: Failed setting op %d err=%d", __FUNCTION__, op, err);
+
+    return err;
+}
+
+int getConfigCount(int /*dpy*/) {
+    int numConfigs = -1;
+    sp<IQService> binder = getBinder();
+    if(binder != NULL) {
+        Parcel inParcel, outParcel;
+        inParcel.writeInt32(DISPLAY_PRIMARY);
+        status_t err = binder->dispatch(IQService::GET_CONFIG_COUNT,
+                &inParcel, &outParcel);
+        if(!err) {
+            numConfigs = outParcel.readInt32();
+            ALOGI("%s() Received num configs %d", __FUNCTION__, numConfigs);
+        } else {
+            ALOGE("%s() failed with err %d", __FUNCTION__, err);
+        }
+    }
+    return numConfigs;
+}
+
+int getActiveConfig(int dpy) {
+    int configIndex = -1;
+    sp<IQService> binder = getBinder();
+    if(binder != NULL) {
+        Parcel inParcel, outParcel;
+        inParcel.writeInt32(dpy);
+        status_t err = binder->dispatch(IQService::GET_ACTIVE_CONFIG,
+                &inParcel, &outParcel);
+        if(!err) {
+            configIndex = outParcel.readInt32();
+            ALOGI("%s() Received active config index %d", __FUNCTION__,
+                    configIndex);
+        } else {
+            ALOGE("%s() failed with err %d", __FUNCTION__, err);
+        }
+    }
+    return configIndex;
+}
+
+int setActiveConfig(int configIndex, int /*dpy*/) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    if(binder != NULL) {
+        Parcel inParcel, outParcel;
+        inParcel.writeInt32(configIndex);
+        inParcel.writeInt32(DISPLAY_PRIMARY);
+        err = binder->dispatch(IQService::SET_ACTIVE_CONFIG,
+                &inParcel, &outParcel);
+        if(!err) {
+            ALOGI("%s() Successfully set active config index %d", __FUNCTION__,
+                    configIndex);
+        } else {
+            ALOGE("%s() failed with err %d", __FUNCTION__, err);
+        }
+    }
+    return err;
+}
+
+DisplayAttributes getDisplayAttributes(int configIndex, int dpy) {
+    DisplayAttributes dpyattr = {};
+    sp<IQService> binder = getBinder();
+    if(binder != NULL) {
+        Parcel inParcel, outParcel;
+        inParcel.writeInt32(configIndex);
+        inParcel.writeInt32(dpy);
+        status_t err = binder->dispatch(
+                IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG, &inParcel,
+                &outParcel);
+        if(!err) {
+            dpyattr.vsync_period = outParcel.readInt32();
+            dpyattr.xres = outParcel.readInt32();
+            dpyattr.yres = outParcel.readInt32();
+            dpyattr.xdpi = outParcel.readFloat();
+            dpyattr.ydpi = outParcel.readFloat();
+            dpyattr.panel_type = outParcel.readInt32();
+            dpyattr.is_yuv = outParcel.readInt32();
+            ALOGI("%s() Received attrs for index %d: xres %d, yres %d",
+                    __FUNCTION__, configIndex, dpyattr.xres, dpyattr.yres);
+        } else {
+            ALOGE("%s() failed with err %d", __FUNCTION__, err);
+        }
+    }
+    return dpyattr;
+}
+
+int setPanelMode(int mode) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    if(binder != NULL) {
+        Parcel inParcel, outParcel;
+        inParcel.writeInt32(mode);
+        err = binder->dispatch(IQService::SET_DISPLAY_MODE,
+                               &inParcel, &outParcel);
+        if(!err) {
+            ALOGI("%s() Successfully set the display mode to %d", __FUNCTION__,
+                  mode);
+        } else {
+            ALOGE("%s() failed with err %d", __FUNCTION__, err);
+        }
+    }
+    return err;
+}
+
+int setPanelBrightness(int level) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+
+    if(binder != NULL) {
+        inParcel.writeInt32(level);
+        status_t err = binder->dispatch(IQService::SET_PANEL_BRIGHTNESS,
+                &inParcel, &outParcel);
+        if(err) {
+            ALOGE("%s() failed with err %d", __FUNCTION__, err);
+        }
+    }
+    return err;
+}
+
+int getPanelBrightness() {
+    int panel_brightness = -1;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+
+    if(binder != NULL) {
+        status_t err = binder->dispatch(IQService::GET_PANEL_BRIGHTNESS,
+                &inParcel, &outParcel);
+        if(!err) {
+            panel_brightness = outParcel.readInt32();
+            ALOGI("%s() Current panel brightness value %d", __FUNCTION__,
+                    panel_brightness);
+        } else {
+            ALOGE("%s() failed with err %d", __FUNCTION__, err);
+        }
+    }
+    return panel_brightness;
+}
+
+}// namespace
+
+// ----------------------------------------------------------------------------
+// Functions for linking dynamically to libqdutils
+// ----------------------------------------------------------------------------
+extern "C" int minHdcpEncryptionLevelChanged(int dpy, int min_enc_level) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(dpy);
+    inParcel.writeInt32(min_enc_level);
+
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED,
+                &inParcel, &outParcel);
+    }
+
+    if(err) {
+        ALOGE("%s: Failed for dpy %d err=%d", __FUNCTION__, dpy, err);
+    } else {
+        err = outParcel.readInt32();
+    }
+
+    return err;
+}
+
+extern "C" int refreshScreen() {
+    int ret = 0;
+    ret = screenRefresh();
+    return ret;
+}
+
+extern "C" int controlPartialUpdate(int dpy, int mode) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    if(binder != NULL) {
+        Parcel inParcel, outParcel;
+        inParcel.writeInt32(dpy);
+        inParcel.writeInt32(mode);
+        err = binder->dispatch(IQService::CONTROL_PARTIAL_UPDATE, &inParcel, &outParcel);
+        if(err != 0) {
+            ALOGE_IF(getBinder(), "%s() failed with err %d", __FUNCTION__, err);
+        } else {
+            return outParcel.readInt32();
+        }
+    }
+
+    return err;
+}
+
diff --git a/sdm845/libqdutils/display_config.h b/sdm845/libqdutils/display_config.h
new file mode 100644
index 0000000..6512bf5
--- /dev/null
+++ b/sdm845/libqdutils/display_config.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2013 - 2016 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation. nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DISPLAY_CONFIG_H
+#define _DISPLAY_CONFIG_H
+
+#include <gralloc_priv.h>
+#include <qdMetaData.h>
+#include <hardware/hwcomposer.h>
+
+// This header is for clients to use to set/get global display configuration.
+// Only primary and external displays are supported here.
+
+namespace qdutils {
+
+
+/* TODO: Have all the common enums that need be exposed to clients and which
+ * are also needed in hwc defined here. Remove such definitions we have in
+ * hwc_utils.h
+ */
+
+// Use this enum to specify the dpy parameters where needed
+enum {
+    DISPLAY_PRIMARY = HWC_DISPLAY_PRIMARY,
+    DISPLAY_EXTERNAL = HWC_DISPLAY_EXTERNAL,
+#ifdef QTI_BSP
+    DISPLAY_TERTIARY = HWC_DISPLAY_TERTIARY,
+#endif
+    DISPLAY_VIRTUAL = HWC_DISPLAY_VIRTUAL,
+};
+
+// External Display states - used in setSecondaryDisplayStatus()
+// To be consistent with the same defined in hwc_utils.h
+enum {
+    EXTERNAL_OFFLINE = 0,
+    EXTERNAL_ONLINE,
+    EXTERNAL_PAUSE,
+    EXTERNAL_RESUME,
+};
+
+enum {
+    DISABLE_METADATA_DYN_REFRESH_RATE = 0,
+    ENABLE_METADATA_DYN_REFRESH_RATE,
+    SET_BINDER_DYN_REFRESH_RATE,
+};
+
+enum {
+    DEFAULT_MODE = 0,
+    VIDEO_MODE,
+    COMMAND_MODE,
+};
+
+enum {
+    DISPLAY_PORT_DEFAULT = 0,
+    DISPLAY_PORT_DSI,
+    DISPLAY_PORT_DTV,
+    DISPLAY_PORT_WRITEBACK,
+    DISPLAY_PORT_LVDS,
+    DISPLAY_PORT_EDP,
+    DISPLAY_PORT_DP,
+};
+
+// Display Attributes that are available to clients of this library
+// Not to be confused with a similar struct in hwc_utils (in the hwc namespace)
+typedef struct DisplayAttributes {
+    uint32_t vsync_period = 0; //nanoseconds
+    uint32_t xres = 0;
+    uint32_t yres = 0;
+    float xdpi = 0.0f;
+    float ydpi = 0.0f;
+    int panel_type = DISPLAY_PORT_DEFAULT;
+    bool is_yuv = false;
+} DisplayAttributes_t;
+
+//=============================================================================
+// The functions below run in the client process and wherever necessary
+// do a binder call to HWC to get/set data.
+
+// Check if external display is connected. Useful to check before making
+// calls for external displays
+// Returns 1 if connected, 0 if disconnected, negative values on errors
+int isExternalConnected(void);
+
+// Get display vsync period which is in nanoseconds
+// i.e vsync_period = 1000000000l / fps
+// Returns 0 on success, negative values on errors
+int getDisplayAttributes(int dpy, DisplayAttributes_t& dpyattr);
+
+// Set HSIC data on a given display ID
+// Returns 0 on success, negative values on errors
+int setHSIC(int dpy, const HSICData_t& hsic_data);
+
+// get the active visible region for the display
+// Returns 0 on success, negative values on errors
+int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect);
+
+// set the view frame information in hwc context from surfaceflinger
+int setViewFrame(int dpy, int l, int t, int r, int b);
+
+// Set the secondary display status(pause/resume/offline etc.,)
+int setSecondaryDisplayStatus(int dpy, uint32_t status);
+
+// Enable/Disable/Set refresh rate dynamically
+int configureDynRefreshRate(uint32_t op, uint32_t refreshRate);
+
+// Returns the number of configs supported for the display on success.
+// Returns -1 on error.
+// Only primary display supported for now, value of dpy ignored.
+int getConfigCount(int dpy);
+
+// Returns the index of config that is current set for the display on success.
+// Returns -1 on error.
+// Only primary display supported for now, value of dpy ignored.
+int getActiveConfig(int dpy);
+
+// Sets the config for the display on success and returns 0.
+// Returns -1 on error.
+// Only primary display supported for now, value of dpy ignored
+int setActiveConfig(int configIndex, int dpy);
+
+// Returns the attributes for the specified config for the display on success.
+// Returns xres and yres as 0 on error.
+// Only primary display supported for now, value of dpy ignored
+DisplayAttributes getDisplayAttributes(int configIndex, int dpy);
+
+// Set the primary display mode to command or video mode
+int setDisplayMode(int mode);
+
+// Sets the panel brightness of the primary display
+int setPanelBrightness(int level);
+
+// Retrieves the current panel brightness value
+int getPanelBrightness();
+
+}; //namespace
+
+#endif
diff --git a/sdm845/libqdutils/profiler.cpp b/sdm845/libqdutils/profiler.cpp
new file mode 100644
index 0000000..810b019
--- /dev/null
+++ b/sdm845/libqdutils/profiler.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2011-2012, 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 LOG_NDDEBUG 0
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+
+#include "profiler.h"
+
+#ifdef DEBUG_CALC_FPS
+
+
+ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::CalcFps) ;
+
+namespace qdutils {
+
+CalcFps::CalcFps() {
+    debug_fps_level = 0;
+    Init();
+}
+
+CalcFps::~CalcFps() {
+}
+
+void CalcFps::Init() {
+    char prop[PROPERTY_VALUE_MAX];
+    property_get("debug.gr.calcfps", prop, "0");
+    debug_fps_level = atoi(prop);
+    if (debug_fps_level > MAX_DEBUG_FPS_LEVEL) {
+        ALOGW("out of range value for debug.gr.calcfps, using 0");
+        debug_fps_level = 0;
+    }
+
+    ALOGD("DEBUG_CALC_FPS: %d", debug_fps_level);
+    populate_debug_fps_metadata();
+}
+
+void CalcFps::Fps() {
+    if (debug_fps_level > 0)
+        calc_fps(ns2us(systemTime()));
+}
+
+void CalcFps::populate_debug_fps_metadata(void)
+{
+    char prop[PROPERTY_VALUE_MAX];
+
+    /*defaults calculation of fps to based on number of frames*/
+    property_get("debug.gr.calcfps.type", prop, "0");
+    debug_fps_metadata.type = (debug_fps_metadata_t::DfmType) atoi(prop);
+
+    /*defaults to 1000ms*/
+    property_get("debug.gr.calcfps.timeperiod", prop, "1000");
+    debug_fps_metadata.time_period = atoi(prop);
+
+    property_get("debug.gr.calcfps.period", prop, "10");
+    debug_fps_metadata.period = atoi(prop);
+
+    if (debug_fps_metadata.period > MAX_FPS_CALC_PERIOD_IN_FRAMES) {
+        debug_fps_metadata.period = MAX_FPS_CALC_PERIOD_IN_FRAMES;
+    }
+
+    /* default ignorethresh_us: 500 milli seconds */
+    property_get("debug.gr.calcfps.ignorethresh_us", prop, "500000");
+    debug_fps_metadata.ignorethresh_us = atoi(prop);
+
+    debug_fps_metadata.framearrival_steps =
+        (unsigned int)(debug_fps_metadata.ignorethresh_us / 16666);
+
+    if (debug_fps_metadata.framearrival_steps > MAX_FRAMEARRIVAL_STEPS) {
+        debug_fps_metadata.framearrival_steps = MAX_FRAMEARRIVAL_STEPS;
+        debug_fps_metadata.ignorethresh_us =
+            debug_fps_metadata.framearrival_steps * 16666;
+    }
+
+    /* 2ms margin of error for the gettimeofday */
+    debug_fps_metadata.margin_us = 2000;
+
+    for (unsigned int i = 0; i < MAX_FRAMEARRIVAL_STEPS; i++)
+        debug_fps_metadata.accum_framearrivals[i] = 0;
+
+    debug_fps_metadata.curr_frame = 0;
+
+    ALOGD("period: %u", debug_fps_metadata.period);
+    ALOGD("ignorethresh_us: %" PRId64, debug_fps_metadata.ignorethresh_us);
+}
+
+void CalcFps::print_fps(float fps)
+{
+    if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type)
+        ALOGD("FPS for last %d frames: %3.2f", debug_fps_metadata.period, fps);
+    else
+        ALOGD("FPS for last (%f ms, %d frames): %3.2f",
+              debug_fps_metadata.time_elapsed,
+              debug_fps_metadata.curr_frame, fps);
+
+    debug_fps_metadata.curr_frame = 0;
+    debug_fps_metadata.time_elapsed = 0.0;
+
+    if (debug_fps_level > 1) {
+        ALOGD("Frame Arrival Distribution:");
+        for (unsigned int i = 0;
+             i < ((debug_fps_metadata.framearrival_steps / 6) + 1);
+             i++) {
+            ALOGD("%" PRId64" %" PRId64" %" PRId64" %" PRId64" %" PRId64" %" PRId64,
+                  debug_fps_metadata.accum_framearrivals[i*6],
+                  debug_fps_metadata.accum_framearrivals[i*6+1],
+                  debug_fps_metadata.accum_framearrivals[i*6+2],
+                  debug_fps_metadata.accum_framearrivals[i*6+3],
+                  debug_fps_metadata.accum_framearrivals[i*6+4],
+                  debug_fps_metadata.accum_framearrivals[i*6+5]);
+        }
+
+        /* We are done with displaying, now clear the stats */
+        for (unsigned int i = 0;
+             i < debug_fps_metadata.framearrival_steps;
+             i++)
+            debug_fps_metadata.accum_framearrivals[i] = 0;
+    }
+    return;
+}
+
+void CalcFps::calc_fps(nsecs_t currtime_us)
+{
+    static nsecs_t oldtime_us = 0;
+
+    nsecs_t diff = currtime_us - oldtime_us;
+
+    oldtime_us = currtime_us;
+
+    if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type &&
+        diff > debug_fps_metadata.ignorethresh_us) {
+        return;
+    }
+
+    if (debug_fps_metadata.curr_frame < MAX_FPS_CALC_PERIOD_IN_FRAMES) {
+        debug_fps_metadata.framearrivals[debug_fps_metadata.curr_frame] = diff;
+    }
+
+    debug_fps_metadata.curr_frame++;
+
+    if (debug_fps_level > 1) {
+        unsigned int currstep =
+            (unsigned int)(diff + debug_fps_metadata.margin_us) / 16666;
+
+        if (currstep < debug_fps_metadata.framearrival_steps) {
+            debug_fps_metadata.accum_framearrivals[currstep-1]++;
+        }
+    }
+
+    if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type) {
+        if (debug_fps_metadata.curr_frame == debug_fps_metadata.period) {
+            /* time to calculate and display FPS */
+            nsecs_t sum = 0;
+            for (unsigned int i = 0; i < debug_fps_metadata.period; i++)
+                sum += debug_fps_metadata.framearrivals[i];
+            print_fps(float(float(debug_fps_metadata.period * 1000000) /
+                                                              (float)sum));
+        }
+    }
+    else if (debug_fps_metadata_t::DFM_TIME == debug_fps_metadata.type) {
+        debug_fps_metadata.time_elapsed += (float)((float)diff/1000.0);
+        if (debug_fps_metadata.time_elapsed >= debug_fps_metadata.time_period) {
+            float fps = float(1000.0 * debug_fps_metadata.curr_frame/
+                                            debug_fps_metadata.time_elapsed);
+            print_fps(fps);
+        }
+    }
+    return;
+}
+};//namespace qomutils
+#endif
diff --git a/sdm845/libqdutils/profiler.h b/sdm845/libqdutils/profiler.h
new file mode 100644
index 0000000..5f270b0
--- /dev/null
+++ b/sdm845/libqdutils/profiler.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2011-2012, 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 INCLUDE_PROFILER
+#define INCLUDE_PROFILER
+
+#include <stdio.h>
+#include <utils/Singleton.h>
+#include <cutils/properties.h>
+#include <cutils/log.h>
+
+#ifndef DEBUG_CALC_FPS
+#define CALC_FPS() ((void)0)
+#define CALC_INIT() ((void)0)
+#else
+#define CALC_FPS() qdutils::CalcFps::getInstance().Fps()
+#define CALC_INIT() qdutils::CalcFps::getInstance().Init()
+using namespace android;
+namespace qdutils {
+class CalcFps : public Singleton<CalcFps> {
+    public:
+    CalcFps();
+    ~CalcFps();
+
+    void Init();
+    void Fps();
+
+    private:
+    static const unsigned int MAX_FPS_CALC_PERIOD_IN_FRAMES = 128;
+    static const unsigned int MAX_FRAMEARRIVAL_STEPS = 50;
+    static const unsigned int MAX_DEBUG_FPS_LEVEL = 2;
+
+    struct debug_fps_metadata_t {
+        /*fps calculation based on time or number of frames*/
+        enum DfmType {
+            DFM_FRAMES = 0,
+            DFM_TIME   = 1,
+        };
+
+        DfmType type;
+
+        /* indicates how much time do we wait till we calculate FPS */
+        unsigned long time_period;
+
+        /*indicates how much time elapsed since we report fps*/
+        float time_elapsed;
+
+        /* indicates how many frames do we wait till we calculate FPS */
+        unsigned int period;
+        /* current frame, will go upto period, and then reset */
+        unsigned int curr_frame;
+        /* frame will arrive at a multiple of 16666 us at the display.
+           This indicates how many steps to consider for our calculations.
+           For example, if framearrival_steps = 10, then the frame that arrived
+           after 166660 us or more will be ignored.
+           */
+        unsigned int framearrival_steps;
+        /* ignorethresh_us = framearrival_steps * 16666 */
+        nsecs_t      ignorethresh_us;
+        /* used to calculate the actual frame arrival step, the times might not be
+           accurate
+           */
+        unsigned int margin_us;
+
+        /* actual data storage */
+        nsecs_t      framearrivals[MAX_FPS_CALC_PERIOD_IN_FRAMES];
+        nsecs_t      accum_framearrivals[MAX_FRAMEARRIVAL_STEPS];
+    };
+
+    private:
+    void populate_debug_fps_metadata(void);
+    void print_fps(float fps);
+    void calc_fps(nsecs_t currtime_us);
+
+    private:
+    debug_fps_metadata_t debug_fps_metadata;
+    unsigned int debug_fps_level;
+};
+};//namespace qdutils
+#endif
+
+#endif // INCLUDE_PROFILER
diff --git a/sdm845/libqdutils/qdMetaData.cpp b/sdm845/libqdutils/qdMetaData.cpp
new file mode 100644
index 0000000..ae23b53
--- /dev/null
+++ b/sdm845/libqdutils/qdMetaData.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2012-2017, 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 <errno.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <cutils/log.h>
+#include <cinttypes>
+#include <gralloc_priv.h>
+#include "qdMetaData.h"
+
+unsigned long getMetaDataSize() {
+    return static_cast<unsigned long>(ROUND_UP_PAGESIZE(sizeof(MetaData_t)));
+}
+
+static int validateAndMap(private_handle_t* handle) {
+    if (private_handle_t::validate(handle)) {
+        ALOGE("%s: Private handle is invalid - handle:%p", __func__, handle);
+        return -1;
+    }
+    if (handle->fd_metadata == -1) {
+        ALOGE("%s: Invalid metadata fd - handle:%p fd: %d",
+                __func__, handle, handle->fd_metadata);
+        return -1;
+    }
+
+    if (!handle->base_metadata) {
+        auto size = getMetaDataSize();
+        void *base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
+                handle->fd_metadata, 0);
+        if (base == reinterpret_cast<void*>(MAP_FAILED)) {
+            ALOGE("%s: metadata mmap failed - handle:%p fd: %d err: %s",
+                __func__, handle, handle->fd_metadata, strerror(errno));
+
+            return -1;
+        }
+        handle->base_metadata = (uintptr_t) base;
+    }
+    return 0;
+}
+
+int setMetaData(private_handle_t *handle, DispParamType paramType,
+                void *param) {
+    auto err = validateAndMap(handle);
+    if (err != 0)
+        return err;
+    return setMetaDataVa(reinterpret_cast<MetaData_t*>(handle->base_metadata),
+                         paramType, param);
+}
+
+int setMetaDataVa(MetaData_t *data, DispParamType paramType,
+                  void *param) {
+    if (data == nullptr)
+        return -EINVAL;
+    // If parameter is NULL reset the specific MetaData Key
+    if (!param) {
+       data->operation &= ~paramType;
+       // param unset
+       return 0;
+    }
+
+    data->operation |= paramType;
+    switch (paramType) {
+        case PP_PARAM_INTERLACED:
+            data->interlaced = *((int32_t *)param);
+            break;
+        case UPDATE_BUFFER_GEOMETRY:
+            data->bufferDim = *((BufferDim_t *)param);
+            break;
+        case UPDATE_REFRESH_RATE:
+            data->refreshrate = *((float *)param);
+            break;
+        case UPDATE_COLOR_SPACE:
+            data->colorSpace = *((ColorSpace_t *)param);
+            break;
+        case MAP_SECURE_BUFFER:
+            data->mapSecureBuffer = *((int32_t *)param);
+            break;
+        case S3D_FORMAT:
+            data->s3dFormat = *((uint32_t *)param);
+            break;
+        case LINEAR_FORMAT:
+            data->linearFormat = *((uint32_t *)param);
+            break;
+        case SET_IGC:
+            data->igc = *((IGC_t *)param);
+            break;
+        case SET_SINGLE_BUFFER_MODE:
+            data->isSingleBufferMode = *((uint32_t *)param);
+            break;
+        case SET_S3D_COMP:
+            data->s3dComp = *((S3DGpuComp_t *)param);
+            break;
+        case SET_VT_TIMESTAMP:
+            data->vtTimeStamp = *((uint64_t *)param);
+            break;
+#ifdef USE_COLOR_METADATA
+        case COLOR_METADATA:
+            data->color = *((ColorMetaData *)param);
+#endif
+            break;
+        default:
+            ALOGE("Unknown paramType %d", paramType);
+            break;
+    }
+    return 0;
+}
+
+int clearMetaData(private_handle_t *handle, DispParamType paramType) {
+    auto err = validateAndMap(handle);
+    if (err != 0)
+        return err;
+    return clearMetaDataVa(reinterpret_cast<MetaData_t *>(handle->base_metadata),
+            paramType);
+}
+
+int clearMetaDataVa(MetaData_t *data, DispParamType paramType) {
+    if (data == nullptr)
+        return -EINVAL;
+    data->operation &= ~paramType;
+    switch (paramType) {
+        case SET_S3D_COMP:
+            data->s3dComp.displayId = -1;
+            data->s3dComp.s3dMode = 0;
+            break;
+        default:
+            ALOGE("Unknown paramType %d", paramType);
+            break;
+    }
+    return 0;
+}
+
+int getMetaData(private_handle_t *handle, DispFetchParamType paramType,
+                                                    void *param) {
+    int ret = validateAndMap(handle);
+    if (ret != 0)
+        return ret;
+    return getMetaDataVa(reinterpret_cast<MetaData_t *>(handle->base_metadata),
+                         paramType, param);
+}
+
+int getMetaDataVa(MetaData_t *data, DispFetchParamType paramType,
+                  void *param) {
+    // Make sure we send 0 only if the operation queried is present
+    int ret = -EINVAL;
+    if (data == nullptr)
+        return ret;
+
+    switch (paramType) {
+        case GET_PP_PARAM_INTERLACED:
+            if (data->operation & PP_PARAM_INTERLACED) {
+                *((int32_t *)param) = data->interlaced;
+                ret = 0;
+            }
+            break;
+        case GET_BUFFER_GEOMETRY:
+            if (data->operation & UPDATE_BUFFER_GEOMETRY) {
+                *((BufferDim_t *)param) = data->bufferDim;
+                ret = 0;
+            }
+            break;
+        case GET_REFRESH_RATE:
+            if (data->operation & UPDATE_REFRESH_RATE) {
+                *((float *)param) = data->refreshrate;
+                ret = 0;
+            }
+            break;
+        case GET_COLOR_SPACE:
+            if (data->operation & UPDATE_COLOR_SPACE) {
+                *((ColorSpace_t *)param) = data->colorSpace;
+                ret = 0;
+            }
+            break;
+        case GET_MAP_SECURE_BUFFER:
+            if (data->operation & MAP_SECURE_BUFFER) {
+                *((int32_t *)param) = data->mapSecureBuffer;
+                ret = 0;
+            }
+            break;
+        case GET_S3D_FORMAT:
+            if (data->operation & S3D_FORMAT) {
+                *((uint32_t *)param) = data->s3dFormat;
+                ret = 0;
+            }
+            break;
+        case GET_LINEAR_FORMAT:
+            if (data->operation & LINEAR_FORMAT) {
+                *((uint32_t *)param) = data->linearFormat;
+                ret = 0;
+            }
+            break;
+        case GET_IGC:
+            if (data->operation & SET_IGC) {
+                *((IGC_t *)param) = data->igc;
+                ret = 0;
+            }
+            break;
+        case GET_SINGLE_BUFFER_MODE:
+            if (data->operation & SET_SINGLE_BUFFER_MODE) {
+                *((uint32_t *)param) = data->isSingleBufferMode;
+                ret = 0;
+            }
+            break;
+        case GET_S3D_COMP:
+            if (data->operation & SET_S3D_COMP) {
+                *((S3DGpuComp_t *)param) = data->s3dComp;
+                ret = 0;
+            }
+            break;
+        case GET_VT_TIMESTAMP:
+            if (data->operation & SET_VT_TIMESTAMP) {
+                *((uint64_t *)param) = data->vtTimeStamp;
+                ret = 0;
+            }
+            break;
+#ifdef USE_COLOR_METADATA
+        case GET_COLOR_METADATA:
+            if (data->operation & COLOR_METADATA) {
+                *((ColorMetaData *)param) = data->color;
+                ret = 0;
+            }
+#endif
+            break;
+        default:
+            ALOGE("Unknown paramType %d", paramType);
+            break;
+    }
+    return ret;
+}
+
+int copyMetaData(struct private_handle_t *src, struct private_handle_t *dst) {
+    auto err = validateAndMap(src);
+    if (err != 0)
+        return err;
+
+    err = validateAndMap(dst);
+    if (err != 0)
+        return err;
+
+    MetaData_t *src_data = reinterpret_cast <MetaData_t *>(src->base_metadata);
+    MetaData_t *dst_data = reinterpret_cast <MetaData_t *>(dst->base_metadata);
+    memcpy(src_data, dst_data, getMetaDataSize());
+    return 0;
+}
+
+int copyMetaDataVaToHandle(MetaData_t *src_data, struct private_handle_t *dst) {
+    int err = -EINVAL;
+    if (src_data == nullptr)
+        return err;
+
+    err = validateAndMap(dst);
+    if (err != 0)
+        return err;
+
+    MetaData_t *dst_data = reinterpret_cast <MetaData_t *>(dst->base_metadata);
+    memcpy(src_data, dst_data, getMetaDataSize());
+    return 0;
+}
+
+int copyMetaDataHandleToVa(struct private_handle_t *src, MetaData_t *dst_data) {
+    int err = -EINVAL;
+    if (dst_data == nullptr)
+        return err;
+
+    err = validateAndMap(src);
+    if (err != 0)
+        return err;
+
+    MetaData_t *src_data = reinterpret_cast <MetaData_t *>(src->base_metadata);
+    memcpy(src_data, dst_data, getMetaDataSize());
+    return 0;
+}
+
+int copyMetaDataVaToVa(MetaData_t *src_data, MetaData_t *dst_data) {
+    int err = -EINVAL;
+    if (src_data == nullptr)
+        return err;
+
+    if (dst_data == nullptr)
+        return err;
+
+    memcpy(src_data, dst_data, getMetaDataSize());
+    return 0;
+}
+
diff --git a/sdm845/libqdutils/qdMetaData.h b/sdm845/libqdutils/qdMetaData.h
new file mode 100644
index 0000000..e704f6c
--- /dev/null
+++ b/sdm845/libqdutils/qdMetaData.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2012-2017, 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 _QDMETADATA_H
+#define _QDMETADATA_H
+
+#ifdef USE_COLOR_METADATA
+#include <color_metadata.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_UBWC_STATS_LENGTH 32
+
+enum ColorSpace_t{
+    ITU_R_601,
+    ITU_R_601_FR,
+    ITU_R_709,
+    ITU_R_2020,
+    ITU_R_2020_FR,
+};
+
+enum IGC_t {
+    IGC_NotSpecified,
+    IGC_sRGB,
+};
+
+struct HSICData_t {
+    int32_t hue;
+    float   saturation;
+    int32_t intensity;
+    float   contrast;
+};
+
+struct BufferDim_t {
+    int32_t sliceWidth;
+    int32_t sliceHeight;
+};
+
+enum UBWC_Version {
+    UBWC_UNUSED      = 0,
+    UBWC_1_0         = 0x1,
+    UBWC_2_0         = 0x2,
+    UBWC_MAX_VERSION = 0xFF,
+};
+
+struct UBWC_2_0_Stats {
+    uint32_t nCRStatsTile32;  /**< UBWC Stats info for  32 Byte Tile */
+    uint32_t nCRStatsTile64;  /**< UBWC Stats info for  64 Byte Tile */
+    uint32_t nCRStatsTile96;  /**< UBWC Stats info for  96 Byte Tile */
+    uint32_t nCRStatsTile128; /**< UBWC Stats info for 128 Byte Tile */
+    uint32_t nCRStatsTile160; /**< UBWC Stats info for 160 Byte Tile */
+    uint32_t nCRStatsTile192; /**< UBWC Stats info for 192 Byte Tile */
+    uint32_t nCRStatsTile256; /**< UBWC Stats info for 256 Byte Tile */
+};
+
+struct UBWCStats {
+    enum UBWC_Version version; /* Union depends on this version. */
+    uint8_t bDataValid;      /* If [non-zero], CR Stats data is valid.
+                               * Consumers may use stats data.
+                               * If [zero], CR Stats data is invalid.
+                               * Consumers *Shall* not use stats data */
+    union {
+        struct UBWC_2_0_Stats ubwc_stats;
+        uint32_t reserved[MAX_UBWC_STATS_LENGTH]; /* This is for future */
+    };
+};
+
+struct S3DGpuComp_t {
+    int32_t displayId; /* on which display S3D is composed by client */
+    uint32_t s3dMode; /* the S3D format of this layer to be accessed by client */
+};
+
+struct MetaData_t {
+    int32_t operation;
+    int32_t interlaced;
+    struct BufferDim_t bufferDim;
+    float refreshrate;
+    enum ColorSpace_t colorSpace;
+    enum IGC_t igc;
+     /* Gralloc sets PRIV_SECURE_BUFFER flag to inform that the buffers are from
+      * ION_SECURE. which should not be mapped. However, for GPU post proc
+      * feature, GFX needs to map this buffer, in the client context and in SF
+      * context, it should not. Hence to differentiate, add this metadata field
+      * for clients to set, and GPU will to read and know when to map the
+      * SECURE_BUFFER(ION) */
+    int32_t mapSecureBuffer;
+    /* The supported formats are defined in gralloc_priv.h to
+     * support legacy code*/
+    uint32_t s3dFormat;
+    /* VENUS output buffer is linear for UBWC Interlaced video */
+    uint32_t linearFormat;
+    /* Set by graphics to indicate that this buffer will be written to but not
+     * swapped out */
+    uint32_t isSingleBufferMode;
+    /* Indicate GPU to draw S3D layer on dedicate display device */
+    struct S3DGpuComp_t s3dComp;
+
+    /* Set by camera to program the VT Timestamp */
+    uint64_t vtTimeStamp;
+#ifdef USE_COLOR_METADATA
+    /* Color Aspects + HDR info */
+    ColorMetaData color;
+#endif
+    /* Consumer should read this data as follows based on
+     * Gralloc flag "interlaced" listed above.
+     * [0] : If it is progressive.
+     * [0] : Top field, if it is interlaced.
+     * [1] : Do not read, if it is progressive.
+     * [1] : Bottom field, if it is interlaced.
+     */
+    struct UBWCStats ubwcCRStats[2];
+};
+
+enum DispParamType {
+    SET_VT_TIMESTAMP         = 0x0001,
+    COLOR_METADATA           = 0x0002,
+    PP_PARAM_INTERLACED      = 0x0004,
+    UNUSED2                  = 0x0008,
+    UNUSED3                  = 0x0010,
+    UNUSED4                  = 0x0020,
+    SET_UBWC_CR_STATS_INFO   = 0x0040,
+    UPDATE_BUFFER_GEOMETRY   = 0x0080,
+    UPDATE_REFRESH_RATE      = 0x0100,
+    UPDATE_COLOR_SPACE       = 0x0200,
+    MAP_SECURE_BUFFER        = 0x0400,
+    S3D_FORMAT               = 0x0800,
+    LINEAR_FORMAT            = 0x1000,
+    SET_IGC                  = 0x2000,
+    SET_SINGLE_BUFFER_MODE   = 0x4000,
+    SET_S3D_COMP             = 0x8000,
+};
+
+enum DispFetchParamType {
+    GET_VT_TIMESTAMP         = 0x0001,
+    GET_COLOR_METADATA       = 0x0002,
+    GET_PP_PARAM_INTERLACED  = 0x0004,
+    GET_UBWC_CR_STATS_INFO   = 0x0040,
+    GET_BUFFER_GEOMETRY      = 0x0080,
+    GET_REFRESH_RATE         = 0x0100,
+    GET_COLOR_SPACE          = 0x0200,
+    GET_MAP_SECURE_BUFFER    = 0x0400,
+    GET_S3D_FORMAT           = 0x0800,
+    GET_LINEAR_FORMAT        = 0x1000,
+    GET_IGC                  = 0x2000,
+    GET_SINGLE_BUFFER_MODE   = 0x4000,
+    GET_S3D_COMP             = 0x8000,
+};
+
+struct private_handle_t;
+int setMetaData(struct private_handle_t *handle, enum DispParamType paramType,
+                void *param);
+int setMetaDataVa(struct MetaData_t* data, enum DispParamType paramType,
+                  void *param);
+
+int getMetaData(struct private_handle_t *handle,
+                enum DispFetchParamType paramType,
+                void *param);
+int getMetaDataVa(struct MetaData_t* data, enum DispFetchParamType paramType,
+                  void *param);
+
+int copyMetaData(struct private_handle_t *src, struct private_handle_t *dst);
+int copyMetaDataVaToHandle(struct MetaData_t *src, struct private_handle_t *dst);
+int copyMetaDataHandleToVa(struct private_handle_t* src, struct MetaData_t *dst);
+int copyMetaDataVaToVa(struct MetaData_t *src, struct MetaData_t *dst);
+
+int clearMetaData(struct private_handle_t *handle, enum DispParamType paramType);
+int clearMetaDataVa(struct MetaData_t *data, enum DispParamType paramType);
+
+unsigned long getMetaDataSize();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _QDMETADATA_H */
+
diff --git a/sdm845/libqdutils/qd_utils.cpp b/sdm845/libqdutils/qd_utils.cpp
new file mode 100644
index 0000000..10ac90b
--- /dev/null
+++ b/sdm845/libqdutils/qd_utils.cpp
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2013, 2017 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 <unistd.h>
+#include <gralloc_priv.h>
+#include "qd_utils.h"
+
+namespace qdutils {
+
+static int parseLine(char *input, char *tokens[], const uint32_t maxToken, uint32_t *count) {
+    char *tmpToken = NULL;
+    char *tmpPtr;
+    uint32_t index = 0;
+    const char *delim = ", =\n";
+    if (!input) {
+      return -1;
+    }
+    tmpToken = strtok_r(input, delim, &tmpPtr);
+    while (tmpToken && index < maxToken) {
+      tokens[index++] = tmpToken;
+      tmpToken = strtok_r(NULL, delim, &tmpPtr);
+    }
+    *count = index;
+
+    return 0;
+}
+
+static int getExternalNode(const char *type) {
+    FILE *displayDeviceFP = NULL;
+    char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
+    char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
+    int j = 0;
+
+    for(j = 0; j < HWC_NUM_DISPLAY_TYPES; j++) {
+        snprintf (msmFbTypePath, sizeof(msmFbTypePath),
+                  "/sys/class/graphics/fb%d/msm_fb_type", j);
+        displayDeviceFP = fopen(msmFbTypePath, "r");
+        if(displayDeviceFP) {
+            fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
+                    displayDeviceFP);
+            if(strncmp(fbType, type, strlen(type)) == 0) {
+                ALOGD("%s: %s is at fb%d", __func__, type, j);
+                fclose(displayDeviceFP);
+                break;
+            }
+            fclose(displayDeviceFP);
+        } else {
+            ALOGE("%s: Failed to open fb node %d", __func__, j);
+        }
+    }
+
+    if (j < HWC_NUM_DISPLAY_TYPES)
+        return j;
+    else
+        ALOGE("%s: Failed to find %s node", __func__, type);
+
+    return -1;
+}
+
+static int querySDEInfoDRM(HWQueryType type, int *value) {
+    char property[PROPERTY_VALUE_MAX] = {0};
+
+    // TODO(user): If future targets don't support WB UBWC, add separate
+    // properties in target specific system.prop and have clients like WFD
+    // directly rely on those.
+    switch(type) {
+    case HAS_UBWC:
+    case HAS_WB_UBWC:  // WFD stack still uses this
+        *value = 1;
+        property_get("debug.gralloc.gfx_ubwc_disable", property, "0");
+        if(!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
+                !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
+            *value = 0;
+        }
+        break;
+    default:
+        ALOGE("Invalid query type %d", type);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+static int querySDEInfoFB(HWQueryType type, int *value) {
+    FILE *fileptr = NULL;
+    const char *featureName;
+    char stringBuffer[MAX_STRING_LENGTH];
+    uint32_t tokenCount = 0;
+    const uint32_t maxCount = 10;
+    char *tokens[maxCount] = { NULL };
+
+    switch(type) {
+    case HAS_UBWC:
+        featureName = "ubwc";
+        break;
+    case HAS_WB_UBWC:
+        featureName = "wb_ubwc";
+        break;
+    default:
+        ALOGE("Invalid query type %d", type);
+        return -EINVAL;
+    }
+
+    fileptr = fopen("/sys/devices/virtual/graphics/fb0/mdp/caps", "rb");
+    if (!fileptr) {
+        ALOGE("File '%s' not found", stringBuffer);
+        return -EINVAL;
+    }
+
+    size_t len = MAX_STRING_LENGTH;
+    ssize_t read;
+    char *line = stringBuffer;
+    while ((read = getline(&line, &len, fileptr)) != -1) {
+        // parse the line and update information accordingly
+        if (parseLine(line, tokens, maxCount, &tokenCount)) {
+            continue;
+        }
+
+        if (strncmp(tokens[0], "features", strlen("features"))) {
+            continue;
+        }
+
+        for (uint32_t i = 0; i < tokenCount; i++) {
+            if (!strncmp(tokens[i], featureName, strlen(featureName))) {
+              *value = 1;
+            }
+        }
+    }
+    fclose(fileptr);
+
+    return 0;
+}
+
+int querySDEInfo(HWQueryType type, int *value) {
+    if (!value) {
+        return -EINVAL;
+    }
+
+    if (getDriverType() ==  DriverType::DRM) {
+        return querySDEInfoDRM(type, value);
+    }
+
+    return querySDEInfoFB(type, value);
+}
+
+int getHDMINode(void) {
+    return getExternalNode("dtv panel");
+}
+
+int getEdidRawData(char *buffer)
+{
+    int size;
+    int edidFile;
+    char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
+    int node_id = getHDMINode();
+
+    if (node_id < 0) {
+        ALOGE("%s no HDMI node found", __func__);
+        return 0;
+    }
+
+    snprintf(msmFbTypePath, sizeof(msmFbTypePath),
+                 "/sys/class/graphics/fb%d/edid_raw_data", node_id);
+
+    edidFile = open(msmFbTypePath, O_RDONLY, 0);
+
+    if (edidFile < 0) {
+        ALOGE("%s no edid raw data found", __func__);
+        return 0;
+    }
+
+    size = (int)read(edidFile, (char*)buffer, EDID_RAW_DATA_SIZE);
+    close(edidFile);
+    return size;
+}
+
+bool isDPConnected() {
+    char connectPath[MAX_FRAME_BUFFER_NAME_SIZE];
+    FILE *connectFile = NULL;
+    size_t len = MAX_STRING_LENGTH;
+    char stringBuffer[MAX_STRING_LENGTH];
+    char *line = stringBuffer;
+
+    int nodeId = getExternalNode("dp panel");
+    if (nodeId < 0) {
+        ALOGE("%s no DP node found", __func__);
+        return false;
+    }
+
+    snprintf(connectPath, sizeof(connectPath),
+             "/sys/class/graphics/fb%d/connected", nodeId);
+
+    connectFile = fopen(connectPath, "rb");
+    if (!connectFile) {
+        ALOGW("Failed to open connect node for device node %d", nodeId);
+        return false;
+    }
+
+    if (getline(&line, &len, connectFile) < 0) {
+        fclose(connectFile);
+        return false;
+    }
+
+    fclose(connectFile);
+
+    return atoi(line);
+}
+
+int getDPTestConfig(uint32_t *panelBpp, uint32_t *patternType) {
+    if (!panelBpp || !patternType) {
+        return -1;
+    }
+
+    char configPath[MAX_FRAME_BUFFER_NAME_SIZE];
+    FILE *configFile = NULL;
+    uint32_t tokenCount = 0;
+    const uint32_t maxCount = 10;
+    char *tokens[maxCount] = { NULL };
+    size_t len = MAX_STRING_LENGTH;
+    char stringBuffer[MAX_STRING_LENGTH];
+    char *line = stringBuffer;
+
+    int nodeId = getExternalNode("dp panel");
+    if (nodeId < 0) {
+        ALOGE("%s no DP node found", __func__);
+        return -EINVAL;
+    }
+
+    snprintf(configPath, sizeof(configPath),
+             "/sys/class/graphics/fb%d/config", nodeId);
+
+    configFile = fopen(configPath, "rb");
+    if (!configFile) {
+        ALOGW("Failed to open config node for device node %d", nodeId);
+        return -EINVAL;
+    }
+
+    while (getline(&line, &len, configFile) != -1) {
+        if (!parseLine(line, tokens, maxCount, &tokenCount)) {
+            if (!strncmp(tokens[0], "bpp", strlen("bpp"))) {
+                *panelBpp = static_cast<uint32_t>(atoi(tokens[1]));
+            } else  if (!strncmp(tokens[0], "pattern", strlen("pattern"))) {
+                *patternType = static_cast<uint32_t>(atoi(tokens[1]));
+            }
+        }
+    }
+
+    fclose(configFile);
+
+    return 0;
+}
+
+DriverType getDriverType() {
+    const char *fb_caps = "/sys/devices/virtual/graphics/fb0/mdp/caps";
+    // 0 - File exists
+    return access(fb_caps, F_OK) ? DriverType::DRM : DriverType::FB;
+}
+
+const char *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_BGR_565:
+    return "BGR_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_YCrCb_420_SP_VENUS:
+    return "YCrCb_420_SP_VENUS";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+    return "YCbCr_420_SP_VENUS_UBWC";
+  case HAL_PIXEL_FORMAT_RGBA_1010102:
+    return "RGBA_1010102";
+  case HAL_PIXEL_FORMAT_ARGB_2101010:
+    return "ARGB_2101010";
+  case HAL_PIXEL_FORMAT_RGBX_1010102:
+    return "RGBX_1010102";
+  case HAL_PIXEL_FORMAT_XRGB_2101010:
+    return "XRGB_2101010";
+  case HAL_PIXEL_FORMAT_BGRA_1010102:
+    return "BGRA_1010102";
+  case HAL_PIXEL_FORMAT_ABGR_2101010:
+    return "ABGR_2101010";
+  case HAL_PIXEL_FORMAT_BGRX_1010102:
+    return "BGRX_1010102";
+  case HAL_PIXEL_FORMAT_XBGR_2101010:
+    return "XBGR_2101010";
+  case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+    return "YCbCr_420_P010";
+  case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+    return "YCbCr_420_TP10_UBWC";
+  default:
+    return "Unknown_format";
+  }
+}
+
+}; //namespace qdutils
diff --git a/sdm845/libqdutils/qd_utils.h b/sdm845/libqdutils/qd_utils.h
new file mode 100644
index 0000000..f3b0c04
--- /dev/null
+++ b/sdm845/libqdutils/qd_utils.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013, 2017 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 or 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 _QD_UTIL_MISC_H
+#define _QD_UTIL_MISC_H
+
+#include <utils/threads.h>
+#include <linux/fb.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include <linux/fb.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/resource.h>
+#include <cutils/properties.h>
+#include <hardware/hwcomposer.h>
+
+namespace qdutils {
+
+enum HWQueryType {
+    HAS_UBWC = 1,
+    HAS_WB_UBWC = 2
+};
+
+enum {
+    EDID_RAW_DATA_SIZE = 640,
+    MAX_FRAME_BUFFER_NAME_SIZE = 128,
+    MAX_SYSFS_FILE_PATH = 255,
+    MAX_STRING_LENGTH = 1024,
+};
+
+int querySDEInfo(HWQueryType type, int *value);
+int getEdidRawData(char *buffer);
+int getHDMINode(void);
+bool isDPConnected();
+int getDPTestConfig(uint32_t *panelBpp, uint32_t *patternType);
+
+enum class DriverType {
+    FB = 0,
+    DRM,
+};
+DriverType getDriverType();
+const char *GetHALPixelFormatString(int format);
+
+}; //namespace qdutils
+#endif
diff --git a/sdm845/libqservice/Android.mk b/sdm845/libqservice/Android.mk
new file mode 100644
index 0000000..9cfdf97
--- /dev/null
+++ b/sdm845/libqservice/Android.mk
@@ -0,0 +1,24 @@
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := libqservice
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libbinder
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdqservice\" -Wno-sign-conversion
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_SRC_FILES               := QService.cpp \
+                                 IQService.cpp \
+                                 IQClient.cpp \
+                                 IQHDMIClient.cpp
+LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
+LOCAL_COPY_HEADERS            := IQService.h \
+                                 IQClient.h \
+                                 QService.h \
+                                 QServiceUtils.h \
+                                 IQHDMIClient.h
+
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/sdm845/libqservice/IQClient.cpp b/sdm845/libqservice/IQClient.cpp
new file mode 100644
index 0000000..a6251c8
--- /dev/null
+++ b/sdm845/libqservice/IQClient.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <utils/Errors.h>
+#include <IQClient.h>
+
+using namespace android;
+
+// ---------------------------------------------------------------------------
+// XXX: Since qservice currently runs as part of hwc instead of a standalone
+// process, the implementation below is overridden and the notifyCallback in
+// hwc_qclient is directly called.
+
+namespace qClient {
+
+enum {
+    NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpQClient : public BpInterface<IQClient>
+{
+public:
+    BpQClient(const sp<IBinder>& impl)
+        : BpInterface<IQClient>(impl) {}
+
+    virtual status_t notifyCallback(uint32_t command,
+            const Parcel* inParcel,
+            Parcel* outParcel) {
+        Parcel data;
+        Parcel *reply = outParcel;
+        data.writeInterfaceToken(IQClient::getInterfaceDescriptor());
+        data.writeInt32(command);
+        if (inParcel->dataAvail())
+            data.appendFrom(inParcel, inParcel->dataPosition(),
+                    inParcel->dataAvail());
+        status_t result = remote()->transact(NOTIFY_CALLBACK, data, reply);
+        return result;
+    }
+};
+
+IMPLEMENT_META_INTERFACE(QClient, "android.display.IQClient");
+
+// ----------------------------------------------------------------------
+//Stub implementation - nothing needed here
+status_t BnQClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case NOTIFY_CALLBACK: {
+            CHECK_INTERFACE(IQClient, data, reply);
+            uint32_t command = data.readInt32();
+            notifyCallback(command, &data, reply);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+
+}
+
+}; // namespace qClient
diff --git a/sdm845/libqservice/IQClient.h b/sdm845/libqservice/IQClient.h
new file mode 100644
index 0000000..7d816d2
--- /dev/null
+++ b/sdm845/libqservice/IQClient.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IQCLIENT_H
+#define ANDROID_IQCLIENT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+
+namespace qClient {
+// ----------------------------------------------------------------------------
+class IQClient : public android::IInterface
+{
+public:
+    DECLARE_META_INTERFACE(QClient);
+    virtual android::status_t notifyCallback(uint32_t command,
+            const android::Parcel* inParcel,
+            android::Parcel* outParcel) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnQClient : public android::BnInterface<IQClient>
+{
+public:
+    virtual android::status_t onTransact( uint32_t code,
+                                          const android::Parcel& data,
+                                          android::Parcel* reply,
+                                          uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace qClient
+
+#endif // ANDROID_IQCLIENT_H
diff --git a/sdm845/libqservice/IQHDMIClient.cpp b/sdm845/libqservice/IQHDMIClient.cpp
new file mode 100644
index 0000000..9f5044a
--- /dev/null
+++ b/sdm845/libqservice/IQHDMIClient.cpp
@@ -0,0 +1,103 @@
+/*
+* Copyright (c) 2014 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*    * Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above
+*      copyright notice, this list of conditions and the following
+*      disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation. nor the names of its
+*      contributors may be used to endorse or promote products derived
+*      from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+#include "IQHDMIClient.h"
+
+using namespace android;
+namespace qClient {
+
+enum {
+    HDMI_CONNECTED = IBinder::FIRST_CALL_TRANSACTION,
+    CEC_MESSAGE_RECEIVED
+};
+
+class BpQHDMIClient : public BpInterface<IQHDMIClient>
+{
+public:
+    BpQHDMIClient(const sp<IBinder>& impl)
+            :BpInterface<IQHDMIClient>(impl)
+    {
+    }
+
+    void onHdmiHotplug(int connected)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IQHDMIClient::getInterfaceDescriptor());
+        data.writeInt32(connected);
+        remote()->transact(HDMI_CONNECTED, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    void onCECMessageRecieved(char *msg, ssize_t len)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IQHDMIClient::getInterfaceDescriptor());
+        data.writeInt32((int32_t)len);
+        void *buf = data.writeInplace(len);
+        if (buf != NULL)
+            memcpy(buf, msg, len);
+        remote()->transact(CEC_MESSAGE_RECEIVED, data, &reply,
+                IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(QHDMIClient,
+        "android.display.IQHDMIClient");
+
+status_t BnQHDMIClient::onTransact(uint32_t code, const Parcel& data,
+        Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case HDMI_CONNECTED: {
+            CHECK_INTERFACE(IQHDMIClient, data, reply);
+            int connected = data.readInt32();
+            onHdmiHotplug(connected);
+            return NO_ERROR;
+        }
+        case CEC_MESSAGE_RECEIVED: {
+            CHECK_INTERFACE(IQHDMIClient, data, reply);
+            ssize_t len = data.readInt32();
+            const void* msg;
+            if(len >= 0 && len <= (ssize_t) data.dataAvail()) {
+                msg = data.readInplace(len);
+            } else {
+                msg = NULL;
+                len = 0;
+            }
+            if (msg != NULL)
+                onCECMessageRecieved((char*) msg, len);
+            return NO_ERROR;
+        }
+        default: {
+            return BBinder::onTransact(code, data, reply, flags);
+        }
+    }
+}
+
+}; //namespace qClient
diff --git a/sdm845/libqservice/IQHDMIClient.h b/sdm845/libqservice/IQHDMIClient.h
new file mode 100644
index 0000000..c3d012a
--- /dev/null
+++ b/sdm845/libqservice/IQHDMIClient.h
@@ -0,0 +1,57 @@
+/*
+* 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 HDMI_EVENTS_LISTENER_H_
+#define HDMI_EVENTS_LISTENER_H_
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+
+namespace qClient {
+
+class IQHDMIClient : public android::IInterface
+{
+public:
+    DECLARE_META_INTERFACE(QHDMIClient);
+    virtual void onHdmiHotplug(int connected) = 0;
+    virtual void onCECMessageRecieved(char *msg, ssize_t len) = 0;
+};
+
+class BnQHDMIClient : public android::BnInterface<IQHDMIClient>
+{
+public:
+    virtual android::status_t onTransact( uint32_t code,
+            const android::Parcel& data,
+            android::Parcel* reply, uint32_t flags = 0);
+};
+
+}; //namespace qhdmi
+
+#endif // HDMI_EVENTS_LISTENER_H_
+
diff --git a/sdm845/libqservice/IQService.cpp b/sdm845/libqservice/IQService.cpp
new file mode 100644
index 0000000..2d0cbfb
--- /dev/null
+++ b/sdm845/libqservice/IQService.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2016, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <binder/IPCThreadState.h>
+#include <utils/Errors.h>
+#include <private/android_filesystem_config.h>
+#include <IQService.h>
+
+#define QSERVICE_DEBUG 0
+
+using namespace android;
+using namespace qClient;
+
+// ---------------------------------------------------------------------------
+
+namespace qService {
+
+class BpQService : public BpInterface<IQService>
+{
+public:
+    BpQService(const sp<IBinder>& impl)
+        : BpInterface<IQService>(impl) {}
+
+    virtual void connect(const sp<IQClient>& client) {
+        ALOGD_IF(QSERVICE_DEBUG, "%s: connect HWC client", __FUNCTION__);
+        Parcel data, reply;
+        data.writeInterfaceToken(IQService::getInterfaceDescriptor());
+        data.writeStrongBinder(IInterface::asBinder(client));
+        remote()->transact(CONNECT_HWC_CLIENT, data, &reply);
+    }
+
+    virtual void connect(const sp<IQHDMIClient>& client) {
+        ALOGD_IF(QSERVICE_DEBUG, "%s: connect HDMI client", __FUNCTION__);
+        Parcel data, reply;
+        data.writeInterfaceToken(IQService::getInterfaceDescriptor());
+        data.writeStrongBinder(IInterface::asBinder(client));
+        remote()->transact(CONNECT_HDMI_CLIENT, data, &reply);
+    }
+
+
+    virtual android::status_t dispatch(uint32_t command, const Parcel* inParcel,
+            Parcel* outParcel) {
+        ALOGD_IF(QSERVICE_DEBUG, "%s: dispatch in:%p", __FUNCTION__, inParcel);
+        status_t err = (status_t) android::FAILED_TRANSACTION;
+        Parcel data;
+        Parcel *reply = outParcel;
+        data.writeInterfaceToken(IQService::getInterfaceDescriptor());
+        if (inParcel && inParcel->dataSize() > 0)
+            data.appendFrom(inParcel, 0, inParcel->dataSize());
+        err = remote()->transact(command, data, reply);
+        return err;
+    }
+};
+
+IMPLEMENT_META_INTERFACE(QService, "android.display.IQService");
+
+// ----------------------------------------------------------------------
+
+status_t BnQService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    ALOGD_IF(QSERVICE_DEBUG, "%s: code: %d", __FUNCTION__, code);
+    // IPC should be from certain processes only
+    IPCThreadState* ipc = IPCThreadState::self();
+    const int callerPid = ipc->getCallingPid();
+    const int callerUid = ipc->getCallingUid();
+
+    const bool permission = (callerUid == AID_MEDIA ||
+            callerUid == AID_GRAPHICS ||
+            callerUid == AID_ROOT ||
+            callerUid == AID_CAMERASERVER ||
+            callerUid == AID_AUDIO ||
+            callerUid == AID_SYSTEM ||
+            callerUid == AID_MEDIA_CODEC);
+
+    if (code == CONNECT_HWC_CLIENT) {
+        CHECK_INTERFACE(IQService, data, reply);
+        if(callerUid != AID_GRAPHICS) {
+            ALOGE("display.qservice CONNECT_HWC_CLIENT access denied: pid=%d uid=%d",
+                   callerPid, callerUid);
+            return PERMISSION_DENIED;
+        }
+        sp<IQClient> client =
+                interface_cast<IQClient>(data.readStrongBinder());
+        connect(client);
+        return NO_ERROR;
+    } else if(code == CONNECT_HDMI_CLIENT) {
+        CHECK_INTERFACE(IQService, data, reply);
+        if(callerUid != AID_SYSTEM && callerUid != AID_ROOT) {
+            ALOGE("display.qservice CONNECT_HDMI_CLIENT access denied: pid=%d uid=%d",
+                   callerPid, callerUid);
+            return PERMISSION_DENIED;
+        }
+        sp<IQHDMIClient> client =
+                interface_cast<IQHDMIClient>(data.readStrongBinder());
+        connect(client);
+        return NO_ERROR;
+    } else if (code > COMMAND_LIST_START && code < COMMAND_LIST_END) {
+        if(!permission) {
+            ALOGE("display.qservice access denied: command=%d pid=%d uid=%d",
+                   code, callerPid, callerUid);
+            return PERMISSION_DENIED;
+        }
+        CHECK_INTERFACE(IQService, data, reply);
+        dispatch(code, &data, reply);
+        return NO_ERROR;
+    } else {
+        return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace qService
diff --git a/sdm845/libqservice/IQService.h b/sdm845/libqservice/IQService.h
new file mode 100644
index 0000000..5e327d7
--- /dev/null
+++ b/sdm845/libqservice/IQService.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2014, 2016 The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IQSERVICE_H
+#define ANDROID_IQSERVICE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/IBinder.h>
+#include <IQClient.h>
+#include <IQHDMIClient.h>
+
+
+namespace qService {
+// ----------------------------------------------------------------------------
+
+class IQService : public android::IInterface
+{
+public:
+    DECLARE_META_INTERFACE(QService);
+    enum {
+        COMMAND_LIST_START = android::IBinder::FIRST_CALL_TRANSACTION,
+        GET_PANEL_BRIGHTNESS = 2, // Provides ability to set the panel brightness
+        SET_PANEL_BRIGHTNESS = 3, // Provides ability to get the panel brightness
+        CONNECT_HWC_CLIENT = 4, // Connect to qservice
+        SCREEN_REFRESH = 5,     // Refresh screen through SF invalidate
+        EXTERNAL_ORIENTATION = 6,// Set external orientation
+        BUFFER_MIRRORMODE = 7,  // Buffer mirrormode
+        CHECK_EXTERNAL_STATUS = 8,// Check status of external display
+        GET_DISPLAY_ATTRIBUTES = 9,// Get display attributes
+        SET_HSIC_DATA = 10,     // Set HSIC on dspp
+        GET_DISPLAY_VISIBLE_REGION = 11,// Get the visibleRegion for dpy
+        SET_SECONDARY_DISPLAY_STATUS = 12,// Sets secondary display status
+        SET_MAX_PIPES_PER_MIXER = 13,// Set max pipes per mixer for MDPComp
+        SET_VIEW_FRAME = 14,    // Set view frame of display
+        DYNAMIC_DEBUG = 15,     // Enable more logging on the fly
+        SET_IDLE_TIMEOUT = 16,  // Set idle timeout for GPU fallback
+        TOGGLE_BWC = 17,           // Toggle BWC On/Off on targets that support
+        /* Enable/Disable/Set refresh rate dynamically */
+        CONFIGURE_DYN_REFRESH_RATE = 18,
+        CONTROL_PARTIAL_UPDATE = 19,   // Provides ability to enable/disable partial update
+        TOGGLE_SCREEN_UPDATES = 20, // Provides ability to set the panel brightness
+        SET_FRAME_DUMP_CONFIG = 21,  // Provides ability to set the frame dump config
+        SET_S3D_MODE = 22, // Set the 3D mode as specified in msm_hdmi_modes.h
+        CONNECT_HDMI_CLIENT = 23,  // Connect HDMI CEC HAL Client
+        QDCM_SVC_CMDS = 24,        // request QDCM services.
+        SET_ACTIVE_CONFIG = 25, //Set a specified display config
+        GET_ACTIVE_CONFIG = 26, //Get the current config index
+        GET_CONFIG_COUNT = 27, //Get the number of supported display configs
+        GET_DISPLAY_ATTRIBUTES_FOR_CONFIG = 28, //Get attr for specified config
+        SET_DISPLAY_MODE = 29, // Set display mode to command or video mode
+        SET_CAMERA_STATUS = 30, // To notify display when camera is on and off
+        MIN_HDCP_ENCRYPTION_LEVEL_CHANGED = 31,
+        GET_BW_TRANSACTION_STATUS = 32, //Client can query BW transaction status.
+        SET_LAYER_MIXER_RESOLUTION = 33, // Enables client to set layer mixer resolution.
+        SET_COLOR_MODE = 34, // Overrides the QDCM mode on the display
+        GET_HDR_CAPABILITIES = 35, // Get HDR capabilities for legacy HWC interface
+        SET_COLOR_MODE_BY_ID = 36, // Overrides the QDCM mode using the given mode ID
+        COMMAND_LIST_END = 400,
+    };
+
+    enum {
+        END = 0,
+        START,
+    };
+
+    enum {
+        DEBUG_ALL,
+        DEBUG_MDPCOMP,
+        DEBUG_VSYNC,
+        DEBUG_VD,
+        DEBUG_PIPE_LIFECYCLE,
+        DEBUG_DRIVER_CONFIG,
+        DEBUG_ROTATOR,
+        DEBUG_QDCM,
+    };
+
+    enum {
+        PREF_POST_PROCESSING,
+        PREF_PARTIAL_UPDATE,
+        ENABLE_PARTIAL_UPDATE,
+    };
+
+    // Register a HWC client that can be notified
+    // This client is generic and is intended to get
+    // dispatches of all events calling into QService
+    virtual void connect(const android::sp<qClient::IQClient>& client) = 0;
+    // Register an HDMI client. This client gets notification of HDMI events
+    // such as plug/unplug and CEC messages
+    virtual void connect(const android::sp<qClient::IQHDMIClient>& client) = 0;
+    // Generic function to dispatch binder commands
+    // The type of command decides how the data is parceled
+    virtual android::status_t dispatch(uint32_t command,
+            const android::Parcel* inParcel,
+            android::Parcel* outParcel) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnQService : public android::BnInterface<IQService>
+{
+public:
+    virtual android::status_t onTransact( uint32_t code,
+                                          const android::Parcel& data,
+                                          android::Parcel* reply,
+                                          uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace qService
+
+#endif // ANDROID_IQSERVICE_H
diff --git a/sdm845/libqservice/Makefile.am b/sdm845/libqservice/Makefile.am
new file mode 100644
index 0000000..79935b8
--- /dev/null
+++ b/sdm845/libqservice/Makefile.am
@@ -0,0 +1,18 @@
+h_sources = IQService.h \
+            IQClient.h
+
+cpp_sources = QService.cpp \
+              IQService.cpp \
+              IQClient.cpp \
+              IQHDMIClient.cpp
+
+library_includedir = $(includedir)
+library_include_HEADERS = $(h_sources)
+
+lib_LTLIBRARIES = libqservice.la
+libqservice_la_CC = @CC@
+libqservice_la_SOURCES = $(cpp_sources)
+libqservice_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"qdqservice\"
+libqservice_la_CPPFLAGS = $(AM_CPPFLAGS)
+libqservice_LDADD = -lhardware -lcutils -llog -lbinder
+libqservice_la_LDFLAGS = -shared -avoid-version
\ No newline at end of file
diff --git a/sdm845/libqservice/QService.cpp b/sdm845/libqservice/QService.cpp
new file mode 100644
index 0000000..546ad7e
--- /dev/null
+++ b/sdm845/libqservice/QService.cpp
@@ -0,0 +1,112 @@
+/*
+ *  Copyright (c) 2012-2014, 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <QService.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+
+#define QSERVICE_DEBUG 0
+
+using namespace android;
+
+namespace qService {
+
+QService* QService::sQService = NULL;
+// ----------------------------------------------------------------------------
+QService::QService()
+{
+    ALOGD_IF(QSERVICE_DEBUG, "QService Constructor invoked");
+}
+
+QService::~QService()
+{
+    ALOGD_IF(QSERVICE_DEBUG,"QService Destructor invoked");
+}
+
+void QService::connect(const sp<qClient::IQClient>& client) {
+    ALOGD_IF(QSERVICE_DEBUG,"HWC client connected");
+    mClient = client;
+}
+
+void QService::connect(const sp<qClient::IQHDMIClient>& client) {
+    ALOGD_IF(QSERVICE_DEBUG,"HDMI client connected");
+    mHDMIClient = client;
+}
+
+status_t QService::dispatch(uint32_t command, const Parcel* inParcel,
+        Parcel* outParcel) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    IPCThreadState* ipc = IPCThreadState::self();
+    //Rewind parcel in case we're calling from the same process
+    bool sameProcess = (ipc->getCallingPid() == getpid());
+    if(sameProcess)
+        inParcel->setDataPosition(0);
+    if (mClient.get()) {
+        ALOGD_IF(QSERVICE_DEBUG, "Dispatching command: %d", command);
+        err = mClient->notifyCallback(command, inParcel, outParcel);
+        //Rewind parcel in case we're calling from the same process
+        if (sameProcess)
+            outParcel->setDataPosition(0);
+    }
+    return err;
+}
+
+void QService::onHdmiHotplug(int connected) {
+    if(mHDMIClient.get()) {
+        ALOGD_IF(QSERVICE_DEBUG, "%s: HDMI hotplug", __FUNCTION__);
+        mHDMIClient->onHdmiHotplug(connected);
+    } else {
+        ALOGW("%s: Failed to get a valid HDMI client", __FUNCTION__);
+    }
+}
+
+void QService::onCECMessageReceived(char *msg, ssize_t len) {
+    if(mHDMIClient.get()) {
+        ALOGD_IF(QSERVICE_DEBUG, "%s: CEC message received", __FUNCTION__);
+        mHDMIClient->onCECMessageRecieved(msg, len);
+    } else {
+        ALOGW("%s: Failed to get a valid HDMI client", __FUNCTION__);
+    }
+}
+
+
+void QService::init()
+{
+    if(!sQService) {
+        sQService = new QService();
+        sp<IServiceManager> sm = defaultServiceManager();
+        sm->addService(String16("display.qservice"), sQService);
+        if(sm->checkService(String16("display.qservice")) != NULL)
+            ALOGD_IF(QSERVICE_DEBUG, "adding display.qservice succeeded");
+        else
+            ALOGD_IF(QSERVICE_DEBUG, "adding display.qservice failed");
+    }
+}
+
+}
diff --git a/sdm845/libqservice/QService.h b/sdm845/libqservice/QService.h
new file mode 100644
index 0000000..bd130fa
--- /dev/null
+++ b/sdm845/libqservice/QService.h
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (c) 2012-2013, 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_QSERVICE_H
+#define ANDROID_QSERVICE_H
+
+#include <utils/Errors.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+#include <binder/IServiceManager.h>
+#include <IQService.h>
+#include <IQClient.h>
+
+struct hwc_context_t;
+
+namespace qService {
+// ----------------------------------------------------------------------------
+
+class QService : public BnQService {
+public:
+    virtual ~QService();
+    virtual void connect(const android::sp<qClient::IQClient>& client);
+    virtual void connect(const android::sp<qClient::IQHDMIClient>& client);
+    virtual android::status_t dispatch(uint32_t command,
+            const android::Parcel* data,
+            android::Parcel* reply);
+    virtual void onHdmiHotplug(int connected);
+    virtual void onCECMessageReceived(char *msg, ssize_t len);
+    static void init();
+private:
+    QService();
+    android::sp<qClient::IQClient> mClient;
+    android::sp<qClient::IQHDMIClient> mHDMIClient;
+    static QService *sQService;
+};
+}; // namespace qService
+#endif // ANDROID_QSERVICE_H
diff --git a/sdm845/libqservice/QServiceUtils.h b/sdm845/libqservice/QServiceUtils.h
new file mode 100644
index 0000000..8f25253
--- /dev/null
+++ b/sdm845/libqservice/QServiceUtils.h
@@ -0,0 +1,102 @@
+/*
+* Copyright (c) 2013-14 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 QSERVICEUTILS_H
+#define QSERVICEUTILS_H
+#include <binder/Parcel.h>
+#include <binder/IServiceManager.h>
+#include <utils/RefBase.h>
+#include <IQService.h>
+
+// ----------------------------------------------------------------------------
+// Helpers
+// ----------------------------------------------------------------------------
+inline android::sp<qService::IQService> getBinder() {
+    android::sp<android::IServiceManager> sm = android::defaultServiceManager();
+    android::sp<qService::IQService> binder =
+            android::interface_cast<qService::IQService>
+            (sm->getService(android::String16("display.qservice")));
+    if (binder == NULL) {
+        ALOGE("%s: invalid binder object", __FUNCTION__);
+    }
+    return binder;
+}
+
+inline android::status_t sendSingleParam(uint32_t command, uint32_t value) {
+    android::status_t err = (android::status_t) android::FAILED_TRANSACTION;
+    android::sp<qService::IQService> binder = getBinder();
+    android::Parcel inParcel, outParcel;
+    inParcel.writeInt32(value);
+    if(binder != NULL) {
+        err = binder->dispatch(command, &inParcel , &outParcel);
+    }
+    return err;
+}
+
+// ----------------------------------------------------------------------------
+// Convenience wrappers that clients can call
+// ----------------------------------------------------------------------------
+inline android::status_t screenRefresh() {
+    return sendSingleParam(qService::IQService::SCREEN_REFRESH, 1);
+}
+
+inline android::status_t toggleScreenUpdate(uint32_t on) {
+    return sendSingleParam(qService::IQService::TOGGLE_SCREEN_UPDATES, on);
+}
+
+inline android::status_t setExtOrientation(uint32_t orientation) {
+    return sendSingleParam(qService::IQService::EXTERNAL_ORIENTATION,
+            orientation);
+}
+
+inline android::status_t setBufferMirrorMode(uint32_t enable) {
+    return sendSingleParam(qService::IQService::BUFFER_MIRRORMODE, enable);
+}
+
+inline android::status_t setCameraLaunchStatus(uint32_t on) {
+    return sendSingleParam(qService::IQService::SET_CAMERA_STATUS, on);
+}
+
+inline bool displayBWTransactionPending() {
+    android::status_t err = (android::status_t) android::FAILED_TRANSACTION;
+    bool ret = false;
+    android::sp<qService::IQService> binder = getBinder();
+    android::Parcel inParcel, outParcel;
+    if(binder != NULL) {
+        err = binder->dispatch(qService::IQService::GET_BW_TRANSACTION_STATUS,
+                &inParcel , &outParcel);
+        if(err != android::NO_ERROR){
+          ALOGE("GET_BW_TRANSACTION_STATUS binder call failed err=%d", err);
+          return ret;
+        }
+    }
+    ret = outParcel.readInt32();
+    return ret;
+}
+#endif /* end of include guard: QSERVICEUTILS_H */
diff --git a/sdm845/sdm/include/core/buffer_allocator.h b/sdm845/sdm/include/core/buffer_allocator.h
new file mode 100644
index 0000000..6d77bcd
--- /dev/null
+++ b/sdm845/sdm/include/core/buffer_allocator.h
@@ -0,0 +1,159 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*  * Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above
+*    copyright notice, this list of conditions and the following
+*    disclaimer in the documentation and/or other materials provided
+*    with the distribution.
+*  * Neither the name of The Linux Foundation nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file buffer_allocator.h
+  @brief Interface file for platform specific buffer allocator.
+
+  @details This interface is used by SDM to allocate internal buffers.
+*/
+
+#ifndef __BUFFER_ALLOCATOR_H__
+#define __BUFFER_ALLOCATOR_H__
+
+#include "layer_buffer.h"
+
+namespace sdm {
+/*! @brief Input configuration set by the client for buffer allocation.
+
+  @sa BufferInfo::BufferConfig
+*/
+
+struct BufferConfig {
+  uint32_t width = 0;                         //!< Specifies buffer width for buffer allocation.
+  uint32_t height = 0;                        //!< Specifies buffer height for buffer allocation.
+  LayerBufferFormat format = kFormatInvalid;  //!< Specifies buffer format for buffer allocation.
+  uint32_t buffer_count = 0;                  //!< Specifies number of buffers to be allocated.
+  bool secure = false;                        //!< Specifies buffer to be allocated from
+                                              //!< secure region.
+  bool cache = false;                         //!< Specifies whether the buffer needs to be cache.
+  bool secure_camera = false;                 //!< Specifies buffer to be allocated from specific
+                                              //!< secure heap and with a specific alignment.
+  bool gfx_client = false;                    //!< Specifies whether buffer is used by gfx.
+};
+
+/*! @brief Holds the information about the allocated buffer.
+
+  @sa BufferAllocator::AllocateBuffer
+  @sa BufferAllocator::FreeBuffer
+  @sa BufferAllocator::GetAllocatedBufferInfo
+*/
+struct AllocatedBufferInfo {
+  int fd = -1;                   //!< Specifies the fd of the allocated buffer.
+  uint32_t stride = 0;           //!< Specifies allocated buffer stride in bytes.
+  uint32_t aligned_width = 0;    //!< Specifies aligned allocated buffer width in pixels.
+  uint32_t aligned_height = 0;   //!< Specifies aligned allocated buffer height in pixels.
+  LayerBufferFormat format = kFormatInvalid;  // Specifies buffer format for allocated buffer.
+  uint32_t size = 0;             //!< Specifies the size of the allocated buffer.
+};
+
+/*! @brief Holds the information about the input/output configuration of an output buffer.
+
+  @sa BufferAllocator::AllocateBuffer
+  @sa BufferAllocator::FreeBuffer
+*/
+struct BufferInfo {
+  BufferConfig buffer_config;             //!< Specifies configuration of a buffer to be allocated.
+  AllocatedBufferInfo alloc_buffer_info;  //!< Specifies buffer information of allocated buffer.
+
+  void *private_data = NULL;              //!< Pointer to private data.
+};
+
+/*! @brief Buffer allocator implemented by the client
+
+  @details This class declares prototype for BufferAllocator methods which must be
+  implemented by the client. Buffer manager in display manager will use these methods to
+  allocate/deallocate buffers for display manager.
+
+  @sa CoreInterface::CreateCore
+*/
+class BufferAllocator {
+ public:
+  /*! @brief Method to allocate ouput buffer for the given input configuration.
+
+    @details This method allocates memory based on input configuration.
+
+    @param[in] buffer_info \link BufferInfo \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError AllocateBuffer(BufferInfo *buffer_info) = 0;
+
+
+  /*! @brief Method to deallocate the ouput buffer.
+
+    @details This method deallocates the memory allocated using AllocateBuffer method.
+
+    @param[in] buffer_info \link BufferInfo \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError FreeBuffer(BufferInfo *buffer_info) = 0;
+
+
+  /*! @brief Method to get the buffer size.
+
+    @details This method returns buffer size for a specific configuration mentioned in buffer info.
+
+    @param[in] buffer_info \link BufferInfo \endlink
+
+    @return \link unsigned int \endlink
+  */
+  virtual uint32_t GetBufferSize(BufferInfo *buffer_info) = 0;
+
+  /*! @brief Method to Get the AllocatedBufferInfo only.
+
+    @details This method populates the AllocatedBufferInfo as per the configuration in BufferInfo,
+    but fd will be invalid.
+
+    @param[in] buffer_info \link BufferInfo \endlink
+
+    @param[out] allocated_buffer_info \link AllocatedBufferInfo \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetAllocatedBufferInfo(const BufferConfig &buffer_config,
+                                              AllocatedBufferInfo *allocated_buffer_info) = 0;
+
+  /*
+   * Retuns a buffer's layout in terms of number of planes, stride and offset of each plane
+   * Input: AllocatedBufferInfo with a valid aligned width, aligned height, SDM format
+   * Output: stride for each plane, offset of each plane from base, number of planes
+   */
+  virtual DisplayError GetBufferLayout(const AllocatedBufferInfo &buf_info,
+                                       uint32_t stride[4], uint32_t offset[4],
+                                       uint32_t *num_planes) { return kErrorNotSupported; }
+
+ protected:
+  virtual ~BufferAllocator() { }
+};
+
+}  // namespace sdm
+
+#endif  // __BUFFER_ALLOCATOR_H__
+
diff --git a/sdm845/sdm/include/core/buffer_sync_handler.h b/sdm845/sdm/include/core/buffer_sync_handler.h
new file mode 100644
index 0000000..1dc5413
--- /dev/null
+++ b/sdm845/sdm/include/core/buffer_sync_handler.h
@@ -0,0 +1,99 @@
+/*
+* 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.
+*/
+
+/*! @file buffer_sync_handler.h
+  @brief Interface file for platform specific buffer allocator.
+
+  @details SDM will use this interface to wait for buffer sync fd to be signaled/merge
+  the two buffer sync fds into one.
+*/
+
+#ifndef __BUFFER_SYNC_HANDLER_H__
+#define __BUFFER_SYNC_HANDLER_H__
+
+#include "sdm_types.h"
+
+namespace sdm {
+
+/*! @brief Buffer sync handler implemented by the client
+
+  @details This class declares prototype for BufferSyncHandler methods which must be
+  implemented by the client. SDM will use these methods to wait for buffer sync fd to be
+  signaled/merge two buffer sync fds into one.
+
+  @sa CoreInterface::CreateCore
+*/
+class BufferSyncHandler {
+ public:
+  /*! @brief Method to wait for ouput buffer to be released.
+
+    @details This method waits for fd to be signaled by the producer/consumer.
+    It is responsibility of the caller to close file descriptor.
+
+    @param[in] fd
+
+    @return \link DisplayError \endlink
+  */
+
+  virtual DisplayError SyncWait(int fd) = 0;
+
+  /*! @brief Method to merge two sync fds into one sync fd
+
+    @details This method merges two buffer sync fds into one sync fd, if a producer/consumer
+    requires to wait for more than one sync fds. It is responsibility of the caller to close file
+    descriptor.
+
+    @param[in] fd1
+    @param[in] fd2
+    @param[out] merged_fd
+
+    @return \link DisplayError \endlink
+ */
+
+  virtual DisplayError SyncMerge(int fd1, int fd2, int *merged_fd) = 0;
+
+  /*! @brief Method to detect if sync fd is signaled
+
+    @details This method detects if sync fd is signaled. It is responsibility of the caller to
+    close file descriptor.
+
+    @param[in] fd
+
+    @return \link Tue if fd has been signaled \endlink
+ */
+  virtual bool IsSyncSignaled(int fd) = 0;
+
+ protected:
+  virtual ~BufferSyncHandler() { }
+};
+
+}  // namespace sdm
+
+#endif  // __BUFFER_SYNC_HANDLER_H__
+
diff --git a/sdm845/sdm/include/core/core_interface.h b/sdm845/sdm/include/core/core_interface.h
new file mode 100644
index 0000000..85001bd
--- /dev/null
+++ b/sdm845/sdm/include/core/core_interface.h
@@ -0,0 +1,231 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file core_interface.h
+  @brief Interface file for core of the display subsystem.
+
+  @details Display core is primarily used for loading and unloading different display device
+  components viz primary, external and virtual. Display core is a statically linked library which
+  runs in caller's process context.
+*/
+#ifndef __CORE_INTERFACE_H__
+#define __CORE_INTERFACE_H__
+
+#include <stdint.h>
+
+#include "display_interface.h"
+#include "sdm_types.h"
+#include "buffer_allocator.h"
+#include "buffer_sync_handler.h"
+#include "socket_handler.h"
+
+/*! @brief Display manager interface version.
+
+  @details Display manager interfaces are version tagged to maintain backward compatibility. This
+  version is supplied as a default argument during display core initialization.
+
+  Client may use an older version of interfaces and link to a higher version of display manager
+  library, but vice versa is not allowed.
+
+  A 32-bit client must use 32-bit display core library and a 64-bit client must use 64-bit display
+  core library.
+
+  Display manager interfaces follow default data structures alignment. Client must not override the
+  default padding rules while using these interfaces.
+
+  @warning It is assumed that client upgrades or downgrades display core interface all at once
+  and recompile all binaries which use these interfaces. Mix and match of these interfaces can
+  lead to unpredictable behaviour.
+
+  @sa CoreInterface::CreateCore
+*/
+#define SDM_REVISION_MAJOR (1)
+#define SDM_REVISION_MINOR (0)
+
+#define SDM_VERSION_TAG ((uint32_t) ((SDM_REVISION_MAJOR << 24) | (SDM_REVISION_MINOR << 16) | \
+                                    (sizeof(SDMCompatibility) << 8) | sizeof(int *)))
+
+namespace sdm {
+
+/*! @brief Forward declaration for debug handler.
+*/
+class DebugHandler;
+
+/*! @brief This enum represents max bandwidth limit mode.
+
+  @sa DisplayInterface::SetMaxBandwidthMode
+*/
+enum HWBwModes {
+  kBwDefault,      //!< Default state. No change in device bandwidth limit.
+  kBwCamera,       //!< Camera is on. Bandwidth limit should be reduced accordingly.
+  kBwVFlip,        //!< VFlip is required. Reduce bandwidth limit accordingly.
+  kBwHFlip,        //!< HFlip is required.  Reduce bandwidth limit accordingly.
+  kBwModeMax,      //!< Limiter for maximum available bandwidth modes.
+};
+
+
+/*! @brief Information on hardware for the first display
+
+  @details This structure returns the display type of the first display on the device
+  (internal display or HDMI etc) and whether it is currently connected,
+
+*/
+struct HWDisplayInterfaceInfo {
+  DisplayType type;
+  bool is_connected;
+};
+
+/*! @brief Display core interface.
+
+  @details This class defines display core interfaces. It contains methods which client shall use
+  to create/destroy different display devices. This interface is created during display core
+  CreateCore() and remains valid until DestroyCore().
+
+  @sa CoreInterface::CreateCore
+  @sa CoreInterface::DestroyCore
+*/
+class CoreInterface {
+ public:
+  /*! @brief Method to create and get handle to display core interface.
+
+    @details This method is the entry point into the display core. Client can create and operate on
+    different display devices only through a valid interface handle obtained using this method. An
+    object of display core is created and handle to this object is returned via output parameter.
+    This interface shall be called only once.
+
+    @param[in] debug_handler \link DebugHandler \endlink
+    @param[in] buffer_allocator \link BufferAllocator \endlink
+    @param[in] buffer_sync_handler \link BufferSyncHandler \endlink
+    @param[out] interface \link CoreInterface \endlink
+    @param[in] version \link SDM_VERSION_TAG \endlink. Client must not override this argument.
+
+    @return \link DisplayError \endlink
+
+    @sa DestroyCore
+  */
+  static DisplayError CreateCore(DebugHandler *debug_handler, BufferAllocator *buffer_allocator,
+                                 BufferSyncHandler *buffer_sync_handler, CoreInterface **interface,
+                                 uint32_t version = SDM_VERSION_TAG);
+
+  /*! @brief Method to create and get handle to display core interface.
+
+    @details This method is the entry point into the display core. Client can create and operate on
+    different display devices only through a valid interface handle obtained using this method. An
+    object of display core is created and handle to this object is returned via output parameter.
+    This interface shall be called only once.
+
+    @param[in] debug_handler \link DebugHandler \endlink
+    @param[in] buffer_allocator \link BufferAllocator \endlink
+    @param[in] buffer_sync_handler \link BufferSyncHandler \endlink
+    @param[in] socket_handler \link SocketHandler \endlink
+    @param[out] interface \link CoreInterface \endlink
+    @param[in] version \link SDM_VERSION_TAG \endlink. Client must not override this argument.
+
+    @return \link DisplayError \endlink
+
+    @sa DestroyCore
+  */
+  static DisplayError CreateCore(DebugHandler *debug_handler, BufferAllocator *buffer_allocator,
+                                 BufferSyncHandler *buffer_sync_handler,
+                                 SocketHandler *socket_handler, CoreInterface **interface,
+                                 uint32_t version = SDM_VERSION_TAG);
+
+  /*! @brief Method to release handle to display core interface.
+
+    @details The object of corresponding display core is destroyed when this method is invoked.
+    Client must explicitly destroy all created display device objects associated with this handle
+    before invoking this method.
+
+    @param[in] interface \link CoreInterface \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa CreateCore
+  */
+  static DisplayError DestroyCore();
+
+  /*! @brief Method to create a display device for a given type.
+
+    @details Client shall use this method to create each of the connected display type. A handle to
+    interface associated with this object is returned via output parameter which can be used to
+    interact further with the display device.
+
+    @param[in] type \link DisplayType \endlink
+    @param[in] event_handler \link DisplayEventHandler \endlink
+    @param[out] interface \link DisplayInterface \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa DestroyDisplay
+  */
+  virtual DisplayError CreateDisplay(DisplayType type, DisplayEventHandler *event_handler,
+                                     DisplayInterface **interface) = 0;
+
+  /*! @brief Method to destroy a display device.
+
+    @details Client shall use this method to destroy each of the created display device objects.
+
+    @param[in] interface \link DisplayInterface \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa CreateDisplay
+  */
+  virtual DisplayError DestroyDisplay(DisplayInterface *interface) = 0;
+
+  /*! @brief Method to update the bandwidth limit as per given mode.
+
+    @param[in] mode indicate the mode or use case
+
+    @return \link DisplayError \endlink
+
+   */
+    virtual DisplayError SetMaxBandwidthMode(HWBwModes mode) = 0;
+
+  /*! @brief Method to get characteristics of the first display.
+
+    @details Client shall use this method to determine if the first display is HDMI, and whether
+    it is currently connected.
+
+    @param[in] hw_disp_info structure that this method will fill up with info.
+
+    @return \link DisplayError \endlink
+
+   */
+    virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) = 0;
+
+
+ protected:
+  virtual ~CoreInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __CORE_INTERFACE_H__
+
diff --git a/sdm845/sdm/include/core/debug_interface.h b/sdm845/sdm/include/core/debug_interface.h
new file mode 100644
index 0000000..da21944
--- /dev/null
+++ b/sdm845/sdm/include/core/debug_interface.h
@@ -0,0 +1,164 @@
+/*
+* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file debug_interface.h
+  @brief This file provides the debug interface for display manager.
+*/
+#ifndef __DEBUG_INTERFACE_H__
+#define __DEBUG_INTERFACE_H__
+
+namespace sdm {
+
+/*! @brief This enum represents different modules/logical unit tags that a log message may
+  be associated with. Client may use this to filter messages for dynamic logging.
+
+  @sa DebugHandler
+*/
+enum DebugTag {
+  kTagNone,             //!< Debug log is not tagged. This type of logs should always be printed.
+  kTagResources,        //!< Debug log is tagged for resource management.
+  kTagStrategy,         //!< Debug log is tagged for strategy decisions.
+  kTagCompManager,      //!< Debug log is tagged for composition manager.
+  kTagDriverConfig,     //!< Debug log is tagged for driver config.
+  kTagRotator,          //!< Debug log is tagged for rotator.
+  kTagScalar,           //!< Debug log is tagged for Scalar Helper.
+  kTagQDCM,             //!< Debug log is tagged for display QDCM color managing.
+  kTagQOSClient,        //!< Debug log is tagged for Qos client
+};
+
+/*! @brief Display debug handler class.
+
+  @details This class defines display debug handler. The handle contains methods which client
+  should implement to get different levels of logging/tracing from display manager. Display manager
+   will call into these methods at appropriate times to send logging/tracing information.
+
+  @sa CoreInterface::CreateCore
+*/
+class DebugHandler {
+ public:
+  /*! @brief Method to handle error messages.
+
+    @param[in] tag \link DebugTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Error(DebugTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to handle warning messages.
+
+    @param[in] tag \link DebugTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Warning(DebugTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to handle informative messages.
+
+    @param[in] tag \link DebugTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Info(DebugTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to handle debug messages.
+
+    @param[in] tag \link DebugTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Debug(DebugTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to handle verbose messages.
+
+    @param[in] tag \link DebugTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Verbose(DebugTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to begin trace for a module/logical unit.
+
+    @param[in] class_name \link name of the class that the function belongs to \endlink
+    @param[in] function_name \link name of the function to be traced \endlink
+    @param[in] custom_string \link custom string for multiple traces within a function \endlink
+  */
+  virtual void BeginTrace(const char *class_name, const char *function_name,
+                          const char *custom_string) = 0;
+
+  /*! @brief Method to end trace for a module/logical unit.
+  */
+  virtual void EndTrace() = 0;
+
+  /*! @brief Method to get property value corresponding to give string.
+
+    @param[in] property_name name of the property
+    @param[out] integer converted value corresponding to the property name
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetProperty(const char *property_name, int *value) = 0;
+
+  /*! @brief Method to get property value corresponding to give string.
+
+   @param[in] property_name name of the property
+   @param[out] string value corresponding to the property name
+
+   @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetProperty(const char *property_name, char *value) = 0;
+
+  /*! @brief Method to set a property to a given string value.
+
+   @param[in] property_name name of the property
+   @param[in] value new value of the property name
+
+   @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetProperty(const char *property_name, const char *value) = 0;
+
+ protected:
+  virtual ~DebugHandler() { }
+};
+
+/*! @brief Scope tracer template class.
+
+  @details This class template implements the funtionality to capture the trace for function/
+  module. It starts the trace upon object creation and ends the trace upon object destruction.
+*/
+template <class T>
+class ScopeTracer {
+ public:
+  ScopeTracer(const char *class_name, const char *function_name) {
+    T::Get()->BeginTrace(class_name, function_name, "");
+  }
+
+  ~ScopeTracer() { T::Get()->EndTrace(); }
+};
+
+}  // namespace sdm
+
+#endif  // __DEBUG_INTERFACE_H__
+
+
+
diff --git a/sdm845/sdm/include/core/display_interface.h b/sdm845/sdm/include/core/display_interface.h
new file mode 100644
index 0000000..524141e
--- /dev/null
+++ b/sdm845/sdm/include/core/display_interface.h
@@ -0,0 +1,674 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file display_interface.h
+  @brief Interface file for display device which represents a physical panel or an output buffer
+  where contents can be rendered.
+
+  @details Display device is used to send layer buffers for composition and get them rendered onto
+  the target device. Each display device represents a unique display target which may be either a
+  physical panel or an output buffer..
+*/
+#ifndef __DISPLAY_INTERFACE_H__
+#define __DISPLAY_INTERFACE_H__
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <utility>
+
+#include "layer_stack.h"
+#include "sdm_types.h"
+
+namespace sdm {
+
+typedef std::vector<std::pair<std::string, std::string>> AttrVal;
+
+/*! @brief This enum represents display device types where contents can be rendered.
+
+  @sa CoreInterface::CreateDisplay
+  @sa CoreInterface::IsDisplaySupported
+*/
+enum DisplayType {
+  kPrimary,         //!< Main physical display which is attached to the handheld device.
+  kHDMI,            //!< HDMI physical display which is generally detachable.
+  kVirtual,         //!< Contents would be rendered into the output buffer provided by the client
+                    //!< e.g. wireless display.
+  kDisplayMax,
+};
+
+/*! @brief This enum represents states of a display device.
+
+  @sa DisplayInterface::GetDisplayState
+  @sa DisplayInterface::SetDisplayState
+*/
+enum DisplayState {
+  kStateOff,        //!< Display is OFF. Contents are not rendered in this state. Client will not
+                    //!< receive VSync events in this state. This is default state as well.
+
+  kStateOn,         //!< Display is ON. Contents are rendered in this state.
+
+  kStateDoze,       //!< Display is ON and it is configured in a low power state.
+
+  kStateDozeSuspend,
+                    //!< Display is ON in a low power state and continue showing its current
+                    //!< contents indefinitely until the mode changes.
+
+  kStateStandby,    //!< Display is OFF. Client will continue to receive VSync events in this state
+                    //!< if VSync is enabled. Contents are not rendered in this state.
+};
+
+/*! @brief This enum represents flags to override detail enhancer parameters.
+
+  @sa DisplayInterface::SetDetailEnhancerData
+*/
+enum DetailEnhancerOverrideFlags {
+  kOverrideDEEnable            = 0x1,     // Specifies to enable detail enhancer
+  kOverrideDESharpen1          = 0x2,     // Specifies user defined Sharpening/smooth for noise
+  kOverrideDESharpen2          = 0x4,     // Specifies user defined Sharpening/smooth for signal
+  kOverrideDEClip              = 0x8,     // Specifies user defined DE clip shift
+  kOverrideDELimit             = 0x10,    // Specifies user defined DE limit value
+  kOverrideDEThrQuiet          = 0x20,    // Specifies user defined DE quiet threshold
+  kOverrideDEThrDieout         = 0x40,    // Specifies user defined DE dieout threshold
+  kOverrideDEThrLow            = 0x80,    // Specifies user defined DE low threshold
+  kOverrideDEThrHigh           = 0x100,   // Specifies user defined DE high threshold
+  kOverrideDEFilterConfig      = 0x200,   // Specifies user defined scaling filter config
+  kOverrideDEMax               = 0xFFFFFFFF,
+};
+
+/*! @brief This enum represents Y/RGB scaling filter configuration.
+
+  @sa DisplayInterface::SetDetailEnhancerData
+*/
+enum ScalingFilterConfig {
+  kFilterEdgeDirected,
+  kFilterCircular,
+  kFilterSeparable,
+  kFilterBilinear,
+  kFilterMax,
+};
+
+/*! @brief This enum represents the quality level of the content.
+
+  @sa DisplayInterface::SetDetailEnhancerData
+*/
+enum ContentQuality {
+  kContentQualityUnknown,  // Default: high artifact and noise
+  kContentQualityLow,      // Low quality content, high artifact and noise,
+  kContentQualityMedium,   // Medium quality, medium artifact and noise,
+  kContentQualityHigh,     // High quality content, low artifact and noise
+  kContentQualityMax,
+};
+
+/*! @brief This enum represents the display port.
+
+  @sa DisplayInterface::GetDisplayPort
+*/
+enum DisplayPort {
+  kPortDefault,
+  kPortDSI,        // Display is connected to DSI port.
+  kPortDTV,        // Display is connected to DTV port
+  kPortWriteBack,  // Display is connected to writeback port
+  kPortLVDS,       // Display is connected to LVDS port
+  kPortEDP,        // Display is connected to EDP port
+  kPortDP,         // Display is connected to DP port.
+};
+
+/*! @brief This structure defines configuration for fixed properties of a display device.
+
+  @sa DisplayInterface::GetConfig
+  @sa DisplayInterface::SetConfig
+*/
+struct DisplayConfigFixedInfo {
+  bool underscan = false;   //!< If display support CE underscan.
+  bool secure = false;      //!< If this display is capable of handling secure content.
+  bool is_cmdmode = false;  //!< If panel is command mode panel.
+  bool hdr_supported = false;  //!< if HDR is enabled
+  uint32_t max_luminance = 0;  //!< From Panel's peak luminance
+  uint32_t average_luminance = 0;  //!< From Panel's average luminance
+  uint32_t min_luminance = 0;  //!< From Panel's blackness level
+};
+
+/*! @brief This structure defines configuration for variable properties of a display device.
+
+  @sa DisplayInterface::GetConfig
+  @sa DisplayInterface::SetConfig
+*/
+struct DisplayConfigVariableInfo {
+  uint32_t x_pixels = 0;          //!< Total number of pixels in X-direction on the display panel.
+  uint32_t y_pixels = 0;          //!< Total number of pixels in Y-direction on the display panel.
+  float x_dpi = 0.0f;             //!< Dots per inch in X-direction.
+  float y_dpi = 0.0f;             //!< Dots per inch in Y-direction.
+  uint32_t fps = 0;               //!< Frame rate per second.
+  uint32_t vsync_period_ns = 0;   //!< VSync period in nanoseconds.
+  bool is_yuv = false;            //!< If the display output is in YUV format.
+};
+
+/*! @brief Event data associated with VSync event.
+
+  @sa DisplayEventHandler::VSync
+*/
+struct DisplayEventVSync {
+  int64_t timestamp = 0;    //!< System monotonic clock timestamp in nanoseconds.
+};
+
+/*! @brief The structure defines the user input for detail enhancer module.
+
+  @sa DisplayInterface::SetDetailEnhancerData
+*/
+struct DisplayDetailEnhancerData {
+  uint32_t override_flags = 0;        // flags to specify which data to be set.
+  uint16_t enable = 0;                // Detail enchancer enable
+  int16_t sharpen_level1 = 0;         // Sharpening/smooth strenght for noise
+  int16_t sharpen_level2 = 0;         // Sharpening/smooth strenght for signal
+  uint16_t clip = 0;                  // DE clip shift
+  uint16_t limit = 0;                 // DE limit value
+  uint16_t thr_quiet = 0;             // DE quiet threshold
+  uint16_t thr_dieout = 0;            // DE dieout threshold
+  uint16_t thr_low = 0;               // DE low threshold
+  uint16_t thr_high = 0;              // DE high threshold
+  int32_t sharp_factor = 50;          // sharp_factor specifies sharpness/smoothness level,
+                                      // range -100..100 positive for sharpness and negative for
+                                      // smoothness
+  ContentQuality quality_level = kContentQualityUnknown;
+                                      // Specifies context quality level
+  ScalingFilterConfig filter_config = kFilterEdgeDirected;
+                                      // Y/RGB filter configuration
+};
+
+/*! @brief Display device event handler implemented by the client.
+
+  @details This class declares prototype for display device event handler methods which must be
+  implemented by the client. Display device will use these methods to notify events to the client.
+  Client must post heavy-weight event handling to a separate thread and unblock display manager
+  thread instantly.
+
+  @sa CoreInterface::CreateDisplay
+*/
+class DisplayEventHandler {
+ public:
+  /*! @brief Event handler for VSync event.
+
+    @details This event is dispatched on every vertical synchronization. The event is disabled by
+    default.
+
+    @param[in] vsync \link DisplayEventVSync \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa DisplayInterface::GetDisplayState
+    @sa DisplayInterface::SetDisplayState
+  */
+  virtual DisplayError VSync(const DisplayEventVSync &vsync) = 0;
+
+  /*! @brief Event handler for Refresh event.
+
+    @details This event is dispatched to trigger a screen refresh. Client must call Prepare() and
+    Commit() in response to it from a separate thread. There is no data associated with this
+    event.
+
+    @return \link DisplayError \endlink
+
+    @sa DisplayInterface::Prepare
+    @sa DisplayInterface::Commit
+  */
+  virtual DisplayError Refresh() = 0;
+
+  /*! @brief Event handler for CEC messages.
+
+    @details This event is dispatched to send CEC messages to the CEC HAL.
+
+    @param[in] message message to be sent
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError CECMessage(char *message) = 0;
+
+ protected:
+  virtual ~DisplayEventHandler() { }
+};
+
+struct PPDisplayAPIPayload;
+struct PPPendingParams;
+
+/*! @brief Display device interface.
+
+  @details This class defines display device interface. It contains methods which client shall use
+  to configure or submit layers for composition on the display device. This interface is created
+  during display device creation and remains valid until destroyed.
+
+  @sa CoreInterface::CreateDisplay
+  @sa CoreInterface::DestroyDisplay
+*/
+class DisplayInterface {
+ public:
+  /*! @brief Method to determine hardware capability to compose layers associated with given frame.
+
+    @details Client shall send all layers associated with a frame targeted for current display
+    using this method and check the layers which can be handled completely in display manager.
+
+    Client shall mark composition type for one of the layer as kCompositionGPUTarget; the GPU
+    composed output would be rendered at the specified layer if some of the layers are not handled
+    by SDM.
+
+    Display manager will set each layer as kCompositionGPU or kCompositionSDE upon return. Client
+    shall render all the layers marked as kCompositionGPU using GPU.
+
+    This method can be called multiple times but only last call prevails. This method must be
+    followed by Commit().
+
+    @param[inout] layer_stack \link LayerStack \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa Commit
+  */
+  virtual DisplayError Prepare(LayerStack *layer_stack) = 0;
+
+  /*! @brief Method to commit layers of a frame submitted in a former call to Prepare().
+
+    @details Client shall call this method to submit layers for final composition. The composed
+    output would be displayed on the panel or written in output buffer.
+
+    Client must ensure that layer stack is same as previous call to Prepare.
+
+    This method shall be called only once for each frame.
+
+    In the event of an error as well, this call will cause any fences returned in the previous call
+    to Commit() to eventually become signaled, so the client's wait on fences can be released to
+    prevent deadlocks.
+
+    @param[in] layer_stack \link LayerStack \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa Prepare
+  */
+  virtual DisplayError Commit(LayerStack *layer_stack) = 0;
+
+  /*! @brief Method to flush any pending buffers/fences submitted previously via Commit() call.
+
+    @details Client shall call this method to request the Display manager to release all buffers and
+    respective fences currently in use. This operation may result in a blank display on the panel
+    until a new frame is submitted for composition.
+
+    @return \link DisplayError \endlink
+
+    @sa Prepare
+    @sa Commit
+  */
+  virtual DisplayError Flush() = 0;
+
+  /*! @brief Method to get current state of the display device.
+
+    @param[out] state \link DisplayState \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa SetDisplayState
+  */
+  virtual DisplayError GetDisplayState(DisplayState *state) = 0;
+
+  /*! @brief Method to get number of configurations(variable properties) supported on the display
+    device.
+
+    @param[out] count Number of modes supported; mode index starts with 0.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count) = 0;
+
+  /*! @brief Method to get configuration for fixed properties of the display device.
+
+    @param[out] fixed_info \link DisplayConfigFixedInfo \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info) = 0;
+
+  /*! @brief Method to get configuration for variable properties of the display device.
+
+    @param[in] index index of the mode
+    @param[out] variable_info \link DisplayConfigVariableInfo \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) = 0;
+
+  /*! @brief Method to get index of active configuration of the display device.
+
+    @param[out] index index of the mode corresponding to variable properties.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetActiveConfig(uint32_t *index) = 0;
+
+  /*! @brief Method to get VSync event state. Default event state is disabled.
+
+    @param[out] enabled vsync state
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetVSyncState(bool *enabled) = 0;
+
+  /*! @brief Method to set current state of the display device.
+
+    @param[in] state \link DisplayState \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa SetDisplayState
+  */
+  virtual DisplayError SetDisplayState(DisplayState state) = 0;
+
+  /*! @brief Method to set active configuration for variable properties of the display device.
+
+    @param[in] variable_info \link DisplayConfigVariableInfo \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info) = 0;
+
+  /*! @brief Method to set active configuration for variable properties of the display device.
+
+    @param[in] index index of the mode corresponding to variable properties.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetActiveConfig(uint32_t index) = 0;
+
+  /*! @brief Method to set VSync event state. Default event state is disabled.
+
+    @param[out] enabled vsync state
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetVSyncState(bool enable) = 0;
+
+  /*! @brief Method to set idle timeout value. Idle fallback is disabled with timeout value 0.
+
+    @param[in] active_ms value in milliseconds.
+
+    @return \link void \endlink
+  */
+  virtual void SetIdleTimeoutMs(uint32_t active_ms) = 0;
+
+  /*! @brief Method to set maximum number of mixer stages for each display.
+
+    @param[in] max_mixer_stages maximum number of mixer stages.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages) = 0;
+
+  /*! @brief Method to control partial update feature for each display.
+
+    @param[in] enable partial update feature control flag
+    @param[out] pending whether the operation is completed or pending for completion
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) = 0;
+
+  /*! @brief Method to disable partial update for at least 1 frame.
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError DisablePartialUpdateOneFrame() = 0;
+
+  /*! @brief Method to set the mode of the primary display.
+
+    @param[in] mode the new display mode.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetDisplayMode(uint32_t mode) = 0;
+
+  /*! @brief Method to get the min and max refresh rate of a display.
+
+    @param[out] min and max refresh rate.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate,
+                                           uint32_t *max_refresh_rate) = 0;
+
+  /*! @brief Method to set the refresh rate of a display.
+
+    @param[in] refresh_rate new refresh rate of the display.
+
+    @param[in] final_rate indicates whether refresh rate is final rate or can be changed by sdm
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate, bool final_rate) = 0;
+
+  /*! @brief Method to query whether scanning is support for the HDMI display.
+
+    @return \link DisplayError \endlink
+  */
+  virtual bool IsUnderscanSupported() = 0;
+
+  /*! @brief Method to set brightness of the primary display.
+
+    @param[in] level the new backlight level.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetPanelBrightness(int level) = 0;
+
+  /*! @brief Method to cache brightness of the primary display.
+
+    @param[in] level the new backlight level.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError CachePanelBrightness(int level) = 0;
+
+  /*! @brief Method to notify display about change in min HDCP encryption level.
+
+    @param[in] min_enc_level minimum encryption level value.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) = 0;
+
+  /*! @brief Method to route display API requests to color service.
+
+    @param[in] in_payload \link PPDisplayAPIPayload \endlink
+    @param[out] out_payload \link PPDisplayPayload \endlink
+    @param[out] pending_action \link PPPendingParams \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+                                            PPDisplayAPIPayload *out_payload,
+                                            PPPendingParams *pending_action) = 0;
+
+  /*! @brief Method to request the number of color modes supported.
+
+    @param[out] mode_count Number of modes
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetColorModeCount(uint32_t *mode_count) = 0;
+
+  /*! @brief Method to request the information of supported color modes.
+
+    @param[inout] mode_count Number of updated modes
+    @param[out] vector of mode strings
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetColorModes(uint32_t *mode_count,
+                                     std::vector<std::string> *color_modes) = 0;
+
+  /*! @brief Method to request the attributes of color mode.
+
+    @param[in] mode name
+    @param[out] vector of mode attributes
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetColorModeAttr(const std::string &color_mode,
+                                        AttrVal *attr_map) = 0;
+
+  /*! @brief Method to set the color mode
+
+    @param[in] mode_name Mode name which needs to be set
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetColorMode(const std::string &color_mode) = 0;
+
+  /*! @brief Method to set the color mode by ID. This method is used for debugging only.
+
+  @param[in] mode_name Mode ID which needs to be set
+
+  @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetColorModeById(int32_t color_mode_id) = 0;
+  /*! @brief Method to set the color transform
+
+    @param[in] length Mode name which needs to be set
+    @param[in] color_transform  4x4 Matrix for color transform
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetColorTransform(const uint32_t length, const double *color_transform) = 0;
+
+  /*! @brief Method to get the default color mode.
+
+    @param[out] default mode name
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetDefaultColorMode(std::string *color_mode) = 0;
+
+  /*! @brief Method to request applying default display mode.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError ApplyDefaultDisplayMode() = 0;
+
+  /*! @brief Method to set the position of the hw cursor.
+
+    @param[in] x \link x position \endlink
+    @param[in] y \link y position \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetCursorPosition(int x, int y) = 0;
+
+  /*! @brief Method to get the brightness level of the display
+
+    @param[out] level brightness level
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetPanelBrightness(int *level) = 0;
+
+  /*! @brief Method to set layer mixer resolution.
+
+    @param[in] width layer mixer width
+    @param[in] height layer mixer height
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height) = 0;
+
+  /*! @brief Method to get layer mixer resolution.
+
+    @param[out] width layer mixer width
+    @param[out] height layer mixer height
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height) = 0;
+
+  /*! @brief Method to set  frame buffer configuration.
+
+    @param[in] variable_info \link DisplayConfigVariableInfo \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) = 0;
+
+  /*! @brief Method to get frame buffer configuration.
+
+    @param[out] variable_info \link DisplayConfigVariableInfo \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) = 0;
+
+  /*! @brief Method to set detail enhancement data.
+
+    @param[in] de_data \link DisplayDetailEnhancerData \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data) = 0;
+
+  /*! @brief Method to get display port information.
+
+    @param[out] port \link DisplayPort \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetDisplayPort(DisplayPort *port) = 0;
+
+  /*! @brief Method to query whether it is Primrary device.
+
+    @return true if this interface is primary.
+  */
+  virtual bool IsPrimaryDisplay() = 0;
+
+  /*! @brief Method to toggle composition types handling by SDM.
+
+    @details Client shall call this method to request SDM to enable/disable a specific type of
+    layer composition. If client disables a composition type, SDM will not handle any of the layer
+    composition using the disabled method in a draw cycle. On lack of resources to handle all
+    layers using other enabled composition methods, Prepare() will return an error.
+
+    Request to toggle composition type is applied from subsequent draw cycles.
+
+    Default state of all defined composition types is enabled.
+
+    @param[in] composition_type \link LayerComposition \endlink
+    @param[in] enable \link enable composition type \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa Prepare
+  */
+  virtual DisplayError SetCompositionState(LayerComposition composition_type, bool enable) = 0;
+
+ protected:
+  virtual ~DisplayInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __DISPLAY_INTERFACE_H__
+
diff --git a/sdm845/sdm/include/core/dump_interface.h b/sdm845/sdm/include/core/dump_interface.h
new file mode 100644
index 0000000..6882e5d
--- /dev/null
+++ b/sdm845/sdm/include/core/dump_interface.h
@@ -0,0 +1,68 @@
+/*
+* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file dump_interface.h
+  @brief Interface file for dump options provided by display manager.
+
+*/
+#ifndef __DUMP_INTERFACE_H__
+#define __DUMP_INTERFACE_H__
+
+#include <stdint.h>
+
+#include "sdm_types.h"
+
+namespace sdm {
+
+/*! @brief Display dump interface.
+
+  @details This class defines dump methods provided by display manager.
+
+*/
+class DumpInterface {
+ public:
+  /*! @brief Method to get dump information in form of a string.
+
+    @details Client shall use this method to get current snapshot of display manager context as a
+    formatted string for logging or dumping purposes.
+
+    @param[inout] buffer String buffer allocated by the client. Filled with null terminated dump
+    information upon return.
+    @param[in] length Length of the string buffer. Length shall be offset adjusted if any.
+
+    @return \link DisplayError \endlink
+
+    @warning Client shall ensure that this interface is not used while a display is being either
+    created or destroyed through display core.
+  */
+  static DisplayError GetDump(char *buffer, uint32_t length);
+
+ protected:
+  virtual ~DumpInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __DUMP_INTERFACE_H__
+
diff --git a/sdm845/sdm/include/core/layer_buffer.h b/sdm845/sdm/include/core/layer_buffer.h
new file mode 100644
index 0000000..c86e020
--- /dev/null
+++ b/sdm845/sdm/include/core/layer_buffer.h
@@ -0,0 +1,283 @@
+/*
+* Copyright (c) 2014, 2016-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file layer_buffer.h
+  @brief File for layer buffer structure.
+
+*/
+#ifndef __LAYER_BUFFER_H__
+#define __LAYER_BUFFER_H__
+
+#include <stdint.h>
+#include <color_metadata.h>
+
+#include "sdm_types.h"
+
+namespace sdm {
+
+/*! @brief This enum represents display layer inverse gamma correction (IGC) types.
+
+  @sa Layer
+*/
+enum LayerIGC {
+  kIGCNotSpecified,       //!< IGC is not specified.
+  kIGCsRGB,               //!< sRGB IGC type.
+};
+
+/*! @brief This enum represents different buffer formats supported by display manager.
+
+  @sa LayerBuffer
+*/
+enum LayerBufferFormat {
+  /* All RGB formats, Any new format will be added towards end of this group to maintain backward
+     compatibility.
+  */
+  kFormatARGB8888,      //!< 8-bits Alpha, Red, Green, Blue interleaved in ARGB order.
+  kFormatRGBA8888,      //!< 8-bits Red, Green, Blue, Alpha interleaved in RGBA order.
+  kFormatBGRA8888,      //!< 8-bits Blue, Green, Red, Alpha interleaved in BGRA order.
+  kFormatXRGB8888,      //!< 8-bits Padding, Red, Green, Blue interleaved in XRGB order. No Alpha.
+  kFormatRGBX8888,      //!< 8-bits Red, Green, Blue, Padding interleaved in RGBX order. No Alpha.
+  kFormatBGRX8888,      //!< 8-bits Blue, Green, Red, Padding interleaved in BGRX order. No Alpha.
+  kFormatRGBA5551,      //!< 5-bits Red, Green, Blue, and 1 bit Alpha interleaved in RGBA order.
+  kFormatRGBA4444,      //!< 4-bits Red, Green, Blue, Alpha interleaved in RGBA order.
+  kFormatRGB888,        //!< 8-bits Red, Green, Blue interleaved in RGB order. No Alpha.
+  kFormatBGR888,        //!< 8-bits Blue, Green, Red interleaved in BGR order. No Alpha.
+  kFormatRGB565,        //!< 5-bit Red, 6-bit Green, 5-bit Blue interleaved in RGB order. No Alpha.
+  kFormatBGR565,        //!< 5-bit Blue, 6-bit Green, 5-bit Red interleaved in BGR order. No Alpha.
+  kFormatRGBA8888Ubwc,  //!< UBWC aligned RGBA8888 format
+  kFormatRGBX8888Ubwc,  //!< UBWC aligned RGBX8888 format
+  kFormatBGR565Ubwc,    //!< UBWC aligned BGR565 format
+  kFormatRGBA1010102,   //!< 10-bits Red, Green, Blue, Alpha interleaved in RGBA order.
+  kFormatARGB2101010,   //!< 10-bits Alpha, Red, Green, Blue interleaved in ARGB order.
+  kFormatRGBX1010102,   //!< 10-bits Red, Green, Blue, Padding interleaved in RGBX order. No Alpha.
+  kFormatXRGB2101010,   //!< 10-bits Padding, Red, Green, Blue interleaved in XRGB order. No Alpha.
+  kFormatBGRA1010102,   //!< 10-bits Blue, Green, Red, Alpha interleaved in BGRA order.
+  kFormatABGR2101010,   //!< 10-bits Alpha, Blue, Green, Red interleaved in ABGR order.
+  kFormatBGRX1010102,   //!< 10-bits Blue, Green, Red, Padding interleaved in BGRX order. No Alpha.
+  kFormatXBGR2101010,   //!< 10-bits Padding, Blue, Green, Red interleaved in XBGR order. No Alpha.
+  kFormatRGBA1010102Ubwc,  //!< UBWC aligned RGBA1010102 format
+  kFormatRGBX1010102Ubwc,  //!< UBWC aligned RGBX1010102 format
+  kFormatRGB101010,     // 10-bits Red, Green, Blue, interleaved in RGB order. No Alpha.
+
+  /* All YUV-Planar formats, Any new format will be added towards end of this group to maintain
+     backward compatibility.
+  */
+  kFormatYCbCr420Planar = 0x100,  //!< Y-plane: y(0), y(1), y(2) ... y(n)
+                                  //!< 2x2 subsampled U-plane: u(0), u(2) ... u(n-1)
+                                  //!< 2x2 subsampled V-plane: v(0), v(2) ... v(n-1)
+
+  kFormatYCrCb420Planar,          //!< Y-plane: y(0), y(1), y(2) ... y(n)
+                                  //!< 2x2 subsampled V-plane: v(0), v(2) ... v(n-1)
+                                  //!< 2x2 subsampled U-plane: u(0), u(2) ... u(n-1)
+
+  kFormatYCrCb420PlanarStride16,  //!< kFormatYCrCb420Planar with stride aligned to 16 bytes
+
+  /* All YUV-Semiplanar formats, Any new format will be added towards end of this group to
+     maintain backward compatibility.
+  */
+  kFormatYCbCr420SemiPlanar = 0x200,  //!< Y-plane: y(0), y(1), y(2) ... y(n)
+                                      //!< 2x2 subsampled interleaved UV-plane:
+                                      //!<    u(0), v(0), u(2), v(2) ... u(n-1), v(n-1)
+                                      //!< aka NV12.
+
+  kFormatYCrCb420SemiPlanar,          //!< Y-plane: y(0), y(1), y(2) ... y(n)
+                                      //!< 2x2 subsampled interleaved VU-plane:
+                                      //!<    v(0), u(0), v(2), u(2) ... v(n-1), u(n-1)
+                                      //!< aka NV21.
+
+  kFormatYCbCr420SemiPlanarVenus,     //!< Y-plane: y(0), y(1), y(2) ... y(n)
+                                      //!< 2x2 subsampled interleaved UV-plane:
+                                      //!<    u(0), v(0), u(2), v(2) ... u(n-1), v(n-1)
+
+  kFormatYCbCr422H1V2SemiPlanar,      //!< Y-plane: y(0), y(1), y(2) ... y(n)
+                                      //!< vertically subsampled interleaved UV-plane:
+                                      //!<    u(0), v(1), u(2), v(3) ... u(n-1), v(n)
+
+  kFormatYCrCb422H1V2SemiPlanar,      //!< Y-plane: y(0), y(1), y(2) ... y(n)
+                                      //!< vertically subsampled interleaved VU-plane:
+                                      //!<    v(0), u(1), v(2), u(3) ... v(n-1), u(n)
+
+  kFormatYCbCr422H2V1SemiPlanar,      //!< Y-plane: y(0), y(1), y(2) ... y(n)
+                                      //!< horizontally subsampled interleaved UV-plane:
+                                      //!<    u(0), v(1), u(2), v(3) ... u(n-1), v(n)
+
+  kFormatYCrCb422H2V1SemiPlanar,      //!< Y-plane: y(0), y(1), y(2) ... y(n)
+                                      //!< horizontally subsampled interleaved VU-plane:
+                                      //!<    v(0), u(1), v(2), u(3) ... v(n-1), u(n)
+
+  kFormatYCbCr420SPVenusUbwc,         //!< UBWC aligned YCbCr420SemiPlanarVenus format
+
+  kFormatYCrCb420SemiPlanarVenus,     //!< Y-plane: y(0), y(1), y(2) ... y(n)
+                                      //!< 2x2 subsampled interleaved UV-plane:
+                                      //!<    v(0), u(0), v(2), u(2) ... v(n-1), u(n-1)
+
+  kFormatYCbCr420P010,                //!< 16 bit Y-plane with 5 MSB bits set to 0:
+                                      //!< y(0), y(1), y(2) ... y(n)
+                                      //!< 2x2 subsampled interleaved 10 bit UV-plane with
+                                      //!< 5 MSB bits set to 0:
+                                      //!<    u(0), v(0), u(2), v(2) ... u(n-1), v(n-1)
+                                      //!< aka P010.
+
+  kFormatYCbCr420TP10Ubwc,            //!< UBWC aligned YCbCr420TP10 format.
+
+  kFormatYCbCr420P010Ubwc,            //!< UBWC aligned YCbCr420P010 format.
+
+  /* All YUV-Packed formats, Any new format will be added towards end of this group to maintain
+     backward compatibility.
+  */
+  kFormatYCbCr422H2V1Packed = 0x300,  //!< Y-plane interleaved with horizontally subsampled U/V by
+                                      //!< factor of 2
+                                      //!<    y(0), u(0), y(1), v(0), y(2), u(2), y(3), v(2)
+                                      //!<    y(n-1), u(n-1), y(n), v(n-1)
+
+  kFormatCbYCrY422H2V1Packed,
+  kFormatInvalid = 0xFFFFFFFF,
+};
+
+
+/*! @brief This enum represents different types of 3D formats supported.
+
+  @sa LayerBufferS3DFormat
+*/
+enum LayerBufferS3DFormat {
+  kS3dFormatNone,            //!< Layer buffer content is not 3D content.
+  kS3dFormatLeftRight,       //!< Left and Right view of a 3D content stitched left and right.
+  kS3dFormatRightLeft,       //!< Right and Left view of a 3D content stitched left and right.
+  kS3dFormatTopBottom,       //!< Left and RightView of a 3D content stitched top and bottom.
+  kS3dFormatFramePacking     //!< Left and right view of 3D content coded in consecutive frames.
+};
+
+/*! @brief This structure defines a color sample plane belonging to a buffer format. RGB buffer
+  formats have 1 plane whereas YUV buffer formats may have upto 4 planes.
+
+  @sa LayerBuffer
+*/
+struct LayerBufferPlane {
+  int fd = -1;           //!< File descriptor referring to the buffer associated with this plane.
+  uint32_t offset = 0;   //!< Offset of the plane in bytes from beginning of the buffer.
+  uint32_t stride = 0;   //!< Stride in bytes i.e. length of a scanline including padding.
+};
+
+/*! @brief This structure defines flags associated with a layer buffer. The 1-bit flag can be set
+  to ON(1) or OFF(0).
+
+  @sa LayerBuffer
+*/
+struct LayerBufferFlags {
+  union {
+    struct {
+      uint32_t secure : 1;          //!< This flag shall be set by client to indicate that the
+                                    //!< buffer need to be handled securely.
+
+      uint32_t video  : 1;          //!< This flag shall be set by client to indicate that the
+                                    //!< buffer is video/ui buffer.
+
+      uint32_t macro_tile : 1;      //!< This flag shall be set by client to indicate that the
+                                    //!< buffer format is macro tiled.
+
+      uint32_t interlace : 1;       //!< This flag shall be set by the client to indicate that
+                                    //!< the buffer has interlaced content.
+
+      uint32_t secure_display : 1;  //!< This flag shall be set by the client to indicate that the
+                                    //!< secure display session is in progress. Secure display
+                                    //!< session can not coexist with non-secure session.
+
+      uint32_t secure_camera : 1;   //!< This flag shall be set by the client to indicate that the
+                                    //!< buffer is associated with secure camera session. A secure
+                                    //!< camera layer can co-exist with non-secure layer(s).
+
+      uint32_t hdr : 1;             //!< This flag shall be set by the client to indicate that the
+                                    //!< the content is HDR.
+    };
+
+    uint32_t flags = 0;             //!< For initialization purpose only.
+                                    //!< Client shall not refer to it directly.
+  };
+};
+
+/*! @brief This structure defines a layer buffer handle which contains raw buffer and its associated
+  properties.
+
+  @sa LayerBuffer
+  @sa LayerStack
+*/
+struct LayerBuffer {
+  uint32_t width = 0;           //!< Aligned width of the Layer that this buffer is for.
+  uint32_t height = 0;          //!< Aligned height of the Layer that this buffer is for.
+  uint32_t unaligned_width = 0;
+                                //!< Unaligned width of the Layer that this buffer is for.
+  uint32_t unaligned_height = 0;
+                                //!< Unaligned height of the Layer that this buffer is for.
+  uint32_t size = 0;            //!< Size of a single buffer (even if multiple clubbed together)
+  LayerBufferFormat format = kFormatRGBA8888;     //!< Format of the buffer content.
+  ColorMetaData color_metadata = {};              //!< CSC + Range + Transfer + Matrix + HDR Info
+  LayerIGC igc = kIGCNotSpecified;                //!< IGC that will be applied on this layer.
+  LayerBufferPlane planes[4] = {};
+                                //!< Array of planes that this buffer contains. RGB buffer formats
+                                //!< have 1 plane whereas YUV buffer formats may have upto 4 planes
+                                //!< Total number of planes for the buffer will be interpreted based
+                                //!< on the buffer format specified.
+
+  int acquire_fence_fd = -1;    //!< File descriptor referring to a sync fence object which will be
+                                //!< signaled when buffer can be read/write by display manager.
+                                //!< This fence object is set by the client during Commit(). For
+                                //!< input buffers client shall signal this fence when buffer
+                                //!< content is available and can be read by display manager. For
+                                //!< output buffers, client shall signal fence when buffer is ready
+                                //!< to be written by display manager.
+
+                                //!< This field is used only during Commit() and shall be set to -1
+                                //!< by the client when buffer is already available for read/write.
+
+  int release_fence_fd = -1;    //!< File descriptor referring to a sync fence object which will be
+                                //!< signaled when buffer has been read/written by display manager.
+                                //!< This fence object is set by display manager during Commit().
+                                //!< For input buffers display manager will signal this fence when
+                                //!< buffer has been consumed. For output buffers, display manager
+                                //!< will signal this fence when buffer is produced.
+
+                                //!< This field is used only during Commit() and will be set to -1
+                                //!< by display manager when buffer is already available for
+                                //!< read/write.
+
+  LayerBufferFlags flags;       //!< Flags associated with this buffer.
+
+  LayerBufferS3DFormat s3d_format = kS3dFormatNone;
+                                //!< Represents the format of the buffer content in 3D. This field
+                                //!< could be modified by both client and SDM.
+  uint64_t buffer_id __attribute__((aligned(8))) = 0;
+                                //!< Specifies the buffer id.
+};
+
+// This enum represents buffer layout types.
+enum BufferLayout {
+  kLinear,    //!< Linear data
+  kUBWC,      //!< UBWC aligned data
+  kTPTiled    //!< Tightly Packed data
+};
+
+}  // namespace sdm
+
+#endif  // __LAYER_BUFFER_H__
+
diff --git a/sdm845/sdm/include/core/layer_stack.h b/sdm845/sdm/include/core/layer_stack.h
new file mode 100644
index 0000000..b8977e2
--- /dev/null
+++ b/sdm845/sdm/include/core/layer_stack.h
@@ -0,0 +1,392 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file layer_stack.h
+  @brief File for display layer stack structure which represents a drawing buffer.
+
+  @details Display layer is a drawing buffer object which will be blended with other drawing buffers
+  under blending rules.
+*/
+#ifndef __LAYER_STACK_H__
+#define __LAYER_STACK_H__
+
+#include <stdint.h>
+#include <utils/constants.h>
+
+#include <vector>
+
+#include "layer_buffer.h"
+#include "sdm_types.h"
+
+namespace sdm {
+
+/*! @brief This enum represents display layer blending types.
+
+  @sa Layer
+*/
+enum LayerBlending {
+  kBlendingPremultiplied,   //!< Pixel color is expressed using premultiplied alpha in RGBA tuples.
+                            //!< If plane alpha is less than 0xFF, apply modulation as well.
+                            //!<   pixel.rgb = src.rgb + dest.rgb x (1 - src.a)
+
+  kBlendingOpaque,          //!< Pixel color is expressed using straight alpha in color tuples. It
+                            //!< is constant blend operation. The layer would appear opaque if plane
+                            //!< alpha is 0xFF.
+
+  kBlendingCoverage,        //!< Pixel color is expressed using straight alpha in color tuples. If
+                            //!< plane alpha is less than 0xff, apply modulation as well.
+                            //!<   pixel.rgb = src.rgb x src.a + dest.rgb x (1 - src.a)
+};
+
+/*! @brief This enum represents display layer composition types.
+
+  @sa Layer
+*/
+enum LayerComposition {
+  /* ==== List of composition types set by SDM === */
+  /* These composition types represent SDM composition decision for the layers which need to
+     be blended. Composition types are set during Prepare() by SDM.
+     Client can set default composition type to any of the below before calling into Prepare(),
+     however client's input value is ignored and does not play any role in composition decision.
+  */
+  kCompositionGPU,          //!< This layer will be drawn onto the target buffer by GPU. Display
+                            //!< device will mark the layer for GPU composition if it can not
+                            //!< handle composition for it.
+                            //!< This composition type is used only if GPUTarget layer is provided
+                            //!< in a composition cycle.
+
+  kCompositionGPUS3D,       //!< This layer will be drawn onto the target buffer in s3d mode by GPU.
+                            //!< Display device will mark the layer for GPU composition if it can
+                            //!< not handle composition for it.
+                            //!< This composition type is used only if GPUTarget layer is provided
+                            //!< in a composition cycle.
+
+  kCompositionSDE,          //!< This layer will be composed by SDE. It must not be composed by
+                            //!< GPU or Blit.
+
+  kCompositionCursor,       // This cursor layer can receive async position updates irrespective of
+                            // dedicated h/w cursor usage. It must not be composed by GPU or Blit
+
+  kCompositionHybrid,       //!< This layer will be drawn by a blit engine and SDE together.
+                            //!< Display device will split the layer, update the blit rectangle
+                            //!< that need to be composed by a blit engine and update original
+                            //!< source rectangle that will be composed by SDE.
+                            //!< This composition type is used only if GPUTarget and BlitTarget
+                            //!< layers are provided in a composition cycle.
+
+  kCompositionBlit,         //!< This layer will be composed using Blit Engine.
+                            //!< This composition type is used only if BlitTarget layer is provided
+                            //!< in a composition cycle.
+
+  /* === List of composition types set by Client === */
+  /* These composition types represent target buffer layers onto which GPU or Blit will draw if SDM
+     decide to have some or all layers drawn by respective composition engine.
+     Client must provide a target buffer layer, if respective composition type is not disabled by
+     an explicit call to SetCompositionState() method. If a composition type is not disabled,
+     providing a target buffer layer is optional. If SDM is unable to handle layers without support
+     of such a composition engine, Prepare() call will return failure.
+  */
+  kCompositionGPUTarget,    //!< This layer will hold result of composition for layers marked for
+                            //!< GPU composition.
+                            //!< If display device does not set any layer for GPU composition then
+                            //!< this layer would be ignored. Else, this layer will be composed
+                            //!< with other layers marked for SDE composition by SDE.
+                            //!< Only one layer shall be marked as target buffer by the caller.
+                            //!< GPU target layer shall be placed after all application layers
+                            //!< in the layer stack.
+
+  kCompositionBlitTarget,   //!< This layer will hold result of composition for blit rectangles
+                            //!< from the layers marked for hybrid composition. Nth blit rectangle
+                            //!< in a layer shall be composed onto Nth blit target.
+                            //!< If display device does not set any layer for hybrid composition
+                            //!< then this would be ignored.
+                            //!< Blit target layers shall be placed after GPUTarget in the layer
+                            //!< stack.
+};
+
+/*! @brief This structure defines rotation and flip values for a display layer.
+
+  @sa Layer
+*/
+struct LayerTransform {
+  float rotation = 0.0f;  //!< Left most pixel coordinate.
+  bool flip_horizontal = false;  //!< Mirror reversal of the layer across a horizontal axis.
+  bool flip_vertical = false;  //!< Mirror reversal of the layer across a vertical axis.
+
+  bool operator==(const LayerTransform& transform) const {
+    return (rotation == transform.rotation && flip_horizontal == transform.flip_horizontal &&
+            flip_vertical == transform.flip_vertical);
+  }
+
+  bool operator!=(const LayerTransform& transform) const {
+    return !operator==(transform);
+  }
+};
+
+/*! @brief This structure defines flags associated with a layer. The 1-bit flag can be set to ON(1)
+  or OFF(0).
+
+  @sa LayerBuffer
+*/
+struct LayerFlags {
+  union {
+    struct {
+      uint32_t skip : 1;      //!< This flag shall be set by client to indicate that this layer
+                              //!< will be handled by GPU. Display Device will not consider it
+                              //!< for composition.
+
+      uint32_t updating : 1;  //!< This flag shall be set by client to indicate that this is
+                              //!< updating non-updating. so strategy manager will mark them for
+                              //!< SDE/GPU composition respectively when the layer stack qualifies
+                              //!< for cache based composition.
+
+      uint32_t solid_fill : 1;
+                              //!< This flag shall be set by client to indicate that this layer
+                              //!< is for solid fill without input buffer. Display Device will
+                              //!< use SDE HW feature to achieve it.
+
+      uint32_t cursor : 1;    //!< This flag shall be set by client to indicate that this layer
+                              //!< is a cursor
+                              //!< Display Device may handle this layer using HWCursor
+
+      uint32_t single_buffer : 1;  //!< This flag shall be set by client to indicate that the layer
+                                   //!< uses only a single buffer that will not be swapped out
+    };
+
+    uint32_t flags = 0;       //!< For initialization purpose only.
+                              //!< Client shall not refer it directly.
+  };
+};
+
+/*! @brief This structure defines flags associated with the layer requests. The 1-bit flag can be
+    set to ON(1) or OFF(0).
+
+  @sa Layer
+*/
+struct LayerRequestFlags {
+  union {
+    struct {
+      uint32_t tone_map : 1;  //!< This flag will be set by SDM when the layer needs tone map
+      uint32_t secure: 1;  //!< This flag will be set by SDM when the layer must be secure
+      uint32_t flip_buffer: 1;  //!< This flag will be set by SDM when the layer needs FBT flip
+    };
+    uint32_t request_flags = 0;  //!< For initialization purpose only.
+                                 //!< Shall not be refered directly.
+  };
+};
+
+/*! @brief This structure defines LayerRequest.
+   Includes width/height/format of the LayerRequest.
+
+   SDM shall set the properties of LayerRequest to be used by the client
+
+  @sa LayerRequest
+*/
+struct LayerRequest {
+  LayerRequestFlags flags;  // Flags associated with this request
+  LayerBufferFormat format = kFormatRGBA8888;  // Requested format
+  uint32_t width = 0;  // Requested unaligned width.
+  uint32_t height = 0;  // Requested unalighed height
+};
+
+/*! @brief This structure defines flags associated with a layer stack. The 1-bit flag can be set to
+  ON(1) or OFF(0).
+
+  @sa LayerBuffer
+*/
+struct LayerStackFlags {
+  union {
+    struct {
+      uint32_t geometry_changed : 1;  //!< This flag shall be set by client to indicate that the
+                                      //!< layer set passed to Prepare() has changed by more than
+                                      //!< just the buffer handles and acquire fences.
+
+      uint32_t skip_present : 1;      //!< This flag will be set to true, if the current layer
+                                      //!< stack contains skip layers.
+
+      uint32_t video_present : 1;     //!< This flag will be set to true, if current layer stack
+                                      //!< contains video.
+
+      uint32_t secure_present : 1;    //!< This flag will be set to true, if the current layer
+                                      //!< stack contains secure layers.
+
+      uint32_t animating : 1;         //!< This flag shall be set by client to indicate that the
+                                      //!<  current frame is animating.i
+
+      uint32_t attributes_changed : 1;
+                                      //!< This flag shall be set by client to indicate that the
+                                      //!< current frame has some properties changed and
+                                      //!< needs re-config.
+
+      uint32_t cursor_present : 1;    //!< This flag will be set to true if the current layer
+                                      //!< stack contains cursor layer.
+
+      uint32_t single_buffered_layer_present : 1;    //!< Set if stack has single buffered layer
+
+      uint32_t s3d_mode_present : 1;  //!< This flag will be set to true, if the current layer
+                                      //!< stack contains s3d layer, and the layer stack can enter
+                                      //!< s3d mode.
+
+      uint32_t post_processed_output : 1;  // If output_buffer should contain post processed output
+                                           // This applies only to primary displays currently
+
+      uint32_t hdr_present : 1;  //!< Set if stack has HDR content
+    };
+
+    uint32_t flags = 0;               //!< For initialization purpose only.
+                                      //!< Client shall not refer it directly.
+  };
+};
+
+/*! @brief This structure defines a rectanglular area inside a display layer.
+
+  @sa LayerRectArray
+*/
+struct LayerRect {
+  float left   = 0.0f;   //!< Left-most pixel coordinate.
+  float top    = 0.0f;   //!< Top-most pixel coordinate.
+  float right  = 0.0f;   //!< Right-most pixel coordinate.
+  float bottom = 0.0f;   //!< Bottom-most pixel coordinate.
+
+  LayerRect() = default;
+
+  LayerRect(float l, float t, float r, float b) : left(l), top(t), right(r), bottom(b) { }
+
+  bool operator==(const LayerRect& rect) const {
+    return left == rect.left && right == rect.right && top == rect.top && bottom == rect.bottom;
+  }
+
+  bool operator!=(const LayerRect& rect) const {
+    return !operator==(rect);
+  }
+};
+
+/*! @brief This structure defines an array of display layer rectangles.
+
+  @sa LayerRect
+*/
+struct LayerRectArray {
+  LayerRect *rect = NULL;  //!< Pointer to first element of array.
+  uint32_t count = 0;      //!< Number of elements in the array.
+};
+
+/*! @brief This structure defines display layer object which contains layer properties and a drawing
+  buffer.
+
+  @sa LayerArray
+*/
+struct Layer {
+  LayerBuffer input_buffer = {};                   //!< Buffer to be composed.
+                                                   //!< If this remains unchanged between two
+                                                   //!< consecutive Prepare() calls and
+                                                   //!< geometry_changed flag is not set for the
+                                                   //!< second call, then the display device will
+                                                   //!< assume that buffer content has not
+                                                   //!< changed.
+
+  LayerComposition composition = kCompositionGPU;  //!< Composition type which can be set by either
+                                                   //!< the client or the display device. This value
+                                                   //!< should be preserved between Prepare() and
+                                                   //!< Commit() calls.
+
+  LayerRect src_rect = {};                         //!< Rectangular area of the layer buffer to
+                                                   //!< consider for composition.
+
+  LayerRect dst_rect = {};                         //!< The target position where the frame will be
+                                                   //!< displayed. Cropping rectangle is scaled to
+                                                   //!< fit into this rectangle. The origin is the
+                                                   //!< top-left corner of the screen.
+
+  std::vector<LayerRect> visible_regions = {};     //!< Visible rectangular areas in screen space.
+                                                   //!< The visible region includes areas overlapped
+                                                   //!< by a translucent layer.
+
+  std::vector<LayerRect> dirty_regions = {};       //!< Rectangular areas in the current frames
+                                                   //!< that have changed in comparison to
+                                                   //!< previous frame.
+
+  std::vector<LayerRect> blit_regions = {};        //!< Rectangular areas of this layer which need
+                                                   //!< to be composed to blit target. Display
+                                                   //!< device will update blit rectangles if a
+                                                   //!< layer composition is set as hybrid. Nth blit
+                                                   //!< rectangle shall be composed onto Nth blit
+                                                   //!< target.
+
+  LayerBlending blending = kBlendingPremultiplied;  //!< Blending operation which need to be
+                                                    //!< applied on the layer buffer during
+                                                    //!< composition.
+
+  LayerTransform transform = {};                   //!< Rotation/Flip operations which need to be
+                                                   //!< applied to the layer buffer during
+                                                   //!< composition.
+
+  uint8_t plane_alpha = 0xff;                      //!< Alpha value applied to the whole layer.
+                                                   //!< Value of each pixel is computed as:
+                                                   //!<    if(kBlendingPremultiplied) {
+                                                   //!<      pixel.RGB = pixel.RGB * planeAlpha/255
+                                                   //!<    }
+                                                   //!<    pixel.a = pixel.a * planeAlpha
+
+  uint32_t frame_rate = 0;                         //!< Rate at which frames are being updated for
+                                                   //!< this layer.
+
+  uint32_t solid_fill_color = 0;                   //!< Solid color used to fill the layer when
+                                                   //!< no content is associated with the layer.
+
+  LayerFlags flags;                                //!< Flags associated with this layer.
+
+  LayerRequest request = {};                       //!< o/p - request on this Layer by SDM.
+
+  Lut3d lut_3d = {};                               //!< o/p - Populated by SDM when tone mapping is
+                                                   //!< needed on this layer.
+};
+
+/*! @brief This structure defines a layer stack that contains layers which need to be composed and
+  rendered onto the target.
+
+  @sa DisplayInterface::Prepare
+  @sa DisplayInterface::Commit
+*/
+struct LayerStack {
+  std::vector<Layer *> layers = {};    //!< Vector of layer pointers.
+
+  int retire_fence_fd = -1;            //!< File descriptor referring to a sync fence object which
+                                       //!< will be signaled when this composited frame has been
+                                       //!< replaced on screen by a subsequent frame on a physical
+                                       //!< display. The fence object is created and returned during
+                                       //!< Commit(). Client shall close the returned file
+                                       //!< descriptor.
+                                       //!< NOTE: This field applies to a physical display only.
+
+  LayerBuffer *output_buffer = NULL;   //!< Pointer to the buffer where composed buffer would be
+                                       //!< rendered for virtual displays.
+                                       //!< NOTE: This field applies to a virtual display only.
+
+  LayerStackFlags flags;               //!< Flags associated with this layer set.
+};
+
+}  // namespace sdm
+
+#endif  // __LAYER_STACK_H__
+
diff --git a/sdm845/sdm/include/core/sdm_types.h b/sdm845/sdm/include/core/sdm_types.h
new file mode 100644
index 0000000..fae1153
--- /dev/null
+++ b/sdm845/sdm/include/core/sdm_types.h
@@ -0,0 +1,74 @@
+/*
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file sdm_types.h
+  @brief This file contains miscellaneous data types used across display interfaces.
+*/
+#ifndef __SDM_TYPES_H__
+#define __SDM_TYPES_H__
+
+namespace sdm {
+
+/*! @brief This enum represents different error codes that display interfaces may return.
+*/
+enum DisplayError {
+  kErrorNone,             //!< Call executed successfully.
+  kErrorUndefined,        //!< An unspecified error has occured.
+  kErrorNotSupported,     //!< Requested operation is not supported.
+  kErrorPermission,       //!< Operation is not permitted in current state.
+  kErrorVersion,          //!< Client is using advanced version of interfaces and calling into an
+                          //!< older version of display library.
+  kErrorDataAlignment,    //!< Client data structures are not aligned on naturual boundaries.
+  kErrorInstructionSet,   //!< 32-bit client is calling into 64-bit library or vice versa.
+  kErrorParameters,       //!< Invalid parameters passed to a method.
+  kErrorFileDescriptor,   //!< Invalid file descriptor.
+  kErrorMemory,           //!< System is running low on memory.
+  kErrorResources,        //!< Not enough hardware resources available to execute call.
+  kErrorHardware,         //!< A hardware error has occured.
+  kErrorTimeOut,          //!< The operation has timed out to prevent client from waiting forever.
+  kErrorShutDown,         //!< Driver is processing shutdown sequence
+  kErrorPerfValidation,   //!< Bandwidth or Clock requirement validation failure.
+  kErrorNoAppLayers,      //!< No App layer(s) in the draw cycle.
+};
+
+/*! @brief This structure is defined for client and library compatibility check purpose only. This
+  structure is used in SDM_VERSION_TAG definition only. Client should not refer it directly for
+  any purpose.
+*/
+struct SDMCompatibility {
+  char c1;
+  int i1;
+  char c2;
+  int i2;
+};
+
+}  // namespace sdm
+
+#endif  // __SDM_TYPES_H__
+
diff --git a/sdm845/sdm/include/core/socket_handler.h b/sdm845/sdm/include/core/socket_handler.h
new file mode 100644
index 0000000..e7fe00e
--- /dev/null
+++ b/sdm845/sdm/include/core/socket_handler.h
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*  * Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above
+*    copyright notice, this list of conditions and the following
+*    disclaimer in the documentation and/or other materials provided
+*    with the distribution.
+*  * Neither the name of The Linux Foundation nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file socket_handler.h
+  @brief Interface file for platform specific Socket Handler.
+
+  @details SDM will use this interface to get the platform specific Socket fd.
+*/
+
+#ifndef __SOCKET_HANDLER_H__
+#define __SOCKET_HANDLER_H__
+
+namespace sdm {
+
+/*! @brief This enum represents Socket types, for which SDM can request the fd.
+
+*/
+enum SocketType {
+  kDpps,       //!< Socket for Dpps
+};
+
+/*! @brief Socket handler implemented by the client
+
+  @details This class declares prototype for SocketHandler methods which must be
+  implemented by client. SDM will use these methods to get the platform specific Socket fd.
+
+  @sa CoreInterface::CreateCore
+*/
+class SocketHandler {
+ public:
+  /*! @brief Method to get the platform specific Socket fd for a given socket type.
+
+    @details This method returns the platform specific Socket fd for a given socket type.
+    It is the responsibility of the caller to close the file descriptor.
+
+    @param[in] socket_type
+
+    @return \link int \endlink
+  */
+
+  virtual int GetSocketFd(SocketType socket_type) = 0;
+
+ protected:
+  virtual ~SocketHandler() { }
+};
+
+}  // namespace sdm
+
+#endif  // __SOCKET_HANDLER_H__
diff --git a/sdm845/sdm/include/private/color_interface.h b/sdm845/sdm/include/private/color_interface.h
new file mode 100644
index 0000000..94be13d
--- /dev/null
+++ b/sdm845/sdm/include/private/color_interface.h
@@ -0,0 +1,88 @@
+/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef __COLOR_INTERFACE_H__
+#define __COLOR_INTERFACE_H__
+
+#include "core/sdm_types.h"
+#include "color_params.h"
+
+namespace sdm {
+
+#define COLORMGR_LIBRARY_NAME "libsdm-color.so"
+#define CREATE_COLOR_INTERFACE_NAME "CreateColorInterface"
+#define DESTROY_COLOR_INTERFACE_NAME "DestroyColorInterface"
+#define COLOR_REVISION_MAJOR (1)
+#define COLOR_REVISION_MINOR (0)
+
+#define COLOR_VERSION_TAG ((uint16_t)((COLOR_REVISION_MAJOR << 8) | COLOR_REVISION_MINOR))
+
+class ColorInterface;
+
+typedef DisplayError (*CreateColorInterface)(uint16_t version, DisplayType type,
+                                             const PPHWAttributes &attributes,
+                                             ColorInterface **interface);
+
+typedef DisplayError (*DestroyColorInterface)(DisplayType type);
+
+class ColorInterface {
+ public:
+  virtual DisplayError ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+                                            PPDisplayAPIPayload *out_payload,
+                                            PPFeaturesConfig *out_features,
+                                            PPPendingParams *pending_action) = 0;
+
+  virtual DisplayError ApplyDefaultDisplayMode(PPFeaturesConfig *out_features) = 0;
+
+  virtual DisplayError ColorIntfSetColorTransform(PPFeaturesConfig *out_features,
+                                                uint32_t disp_id, uint32_t length,
+                                                const double *trans_data) = 0;
+
+  virtual DisplayError ColorIntfSetDisplayMode(PPFeaturesConfig *out_features,
+                                             uint32_t disp_id, int32_t mode_id) = 0;
+
+  virtual DisplayError ColorIntfGetNumDisplayModes(PPFeaturesConfig *out_features,
+                                                 uint32_t disp_id, uint32_t *mode_cnt) = 0;
+
+  virtual DisplayError ColorIntfEnumerateDisplayModes(PPFeaturesConfig *out_features,
+                                                uint32_t disp_id, SDEDisplayMode *modes,
+                                                uint32_t *mode_cnt) = 0;
+  virtual DisplayError ColorIntfGetModeInfo(PPFeaturesConfig *out_features,
+                                            uint32_t disp_id, int32_t mode_id,
+                                            AttrVal *query) = 0;
+  virtual DisplayError ColorIntfGetDefaultModeID(PPFeaturesConfig *out_features,
+                                                 uint32_t disp_id, int32_t *mode_id) = 0;
+
+ protected:
+  virtual ~ColorInterface() {}
+};
+
+}  // namespace sdm
+
+#endif  // __COLOR_INTERFACE_H__
diff --git a/sdm845/sdm/include/private/color_params.h b/sdm845/sdm/include/private/color_params.h
new file mode 100644
index 0000000..0a53832
--- /dev/null
+++ b/sdm845/sdm/include/private/color_params.h
@@ -0,0 +1,611 @@
+/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef __COLOR_PARAMS_H__
+#define __COLOR_PARAMS_H__
+
+#include <stdio.h>
+#include <string.h>
+#include <utils/locker.h>
+#include <utils/constants.h>
+#include <core/sdm_types.h>
+#include <core/display_interface.h>
+
+#include <string>
+
+#include "hw_info_types.h"
+
+namespace sdm {
+
+// Bitmap Pending action to indicate to the caller what's pending to be taken care of.
+enum PendingAction {
+  kInvalidating = BITMAP(0),
+  kApplySolidFill = BITMAP(1),
+  kDisableSolidFill = BITMAP(2),
+  kEnterQDCMMode = BITMAP(3),
+  kExitQDCMMode = BITMAP(4),
+  kSetPanelBrightness = BITMAP(5),
+  kEnableFrameCapture = BITMAP(6),
+  kDisableFrameCapture = BITMAP(7),
+  kConfigureDetailedEnhancer = BITMAP(8),
+  kInvalidatingAndkSetPanelBrightness = BITMAP(9),
+  kGetDetailedEnhancerData = BITMAP(21),
+  kNoAction = BITMAP(31),
+};
+
+static const uint32_t kOpsEnable = BITMAP(0);
+static const uint32_t kOpsRead = BITMAP(1);
+static const uint32_t kOpsWrite = BITMAP(2);
+static const uint32_t kOpsDisable = BITMAP(3);
+
+static const uint32_t kOpsGc8BitRoundEnable = BITMAP(4);
+
+static const uint32_t kPaHueEnable = BITMAP(4);
+static const uint32_t kPaSatEnable = BITMAP(5);
+static const uint32_t kPaValEnable = BITMAP(6);
+static const uint32_t kPaContEnable = BITMAP(7);
+
+static const uint32_t kPaSixZoneEnable = BITMAP(8);
+static const uint32_t kPaSkinEnable = BITMAP(9);
+static const uint32_t kPaSkyEnable = BITMAP(10);
+static const uint32_t kPaFoliageEnable = BITMAP(11);
+
+static const uint32_t kLeftSplitMode = BITMAP(28);   // 0x10000000
+static const uint32_t kRightSplitMode = BITMAP(29);  // 0x20000000
+
+static const int32_t kInvalidModeId = -1;
+
+static const std::string kDynamicRangeAttribute = "DynamicRange";
+static const std::string kColorGamutAttribute = "ColorGamut";
+static const std::string kPictureQualityAttribute = "PictureQuality";
+
+static const std::string kHdr = "hdr";
+static const std::string kSdr = "sdr";
+
+static const std::string kNative = "native";
+static const std::string kDcip3 = "dci_p3";
+static const std::string kSrgb = "srgb";
+static const std::string kDisplayP3 = "display_p3";
+
+static const std::string kVivid = "vivid";
+static const std::string kSharp = "sharp";
+static const std::string kStandard = "standard";
+
+// Enum to identify type of dynamic range of color mode.
+enum DynamicRangeType {
+  kSdrType,
+  kHdrType,
+};
+
+// ENUM to identify different Postprocessing feature block to program.
+// Note: For each new entry added here, also need update hw_interface::GetPPFeaturesVersion<>
+// AND HWPrimary::SetPPFeatures<>.
+enum PPGlobalColorFeatureID {
+  kGlobalColorFeaturePcc,
+  kGlobalColorFeatureIgc,
+  kGlobalColorFeaturePgc,
+  kMixerColorFeatureGc,
+  kGlobalColorFeaturePaV2,
+  kGlobalColorFeatureDither,
+  kGlobalColorFeatureGamut,
+  kGlobalColorFeaturePADither,
+  kMaxNumPPFeatures,
+};
+
+struct PPPendingParams {
+  PendingAction action = kNoAction;
+  void *params = NULL;
+};
+
+struct PPColorInfo {
+  uint32_t r_bitdepth = 0;
+  uint32_t r = 0;
+  uint32_t g_bitdepth = 0;
+  uint32_t g = 0;
+  uint32_t b_bitdepth = 0;
+  uint32_t b = 0;
+};
+
+struct PPColorFillParams {
+  uint32_t flags = 0;
+  struct {
+    uint32_t width = 0;
+    uint32_t height = 0;
+    int32_t x = 0;
+    int32_t y = 0;
+  } rect;
+
+  PPColorInfo color;
+};
+
+struct PPFeatureVersion {
+  // SDE ASIC versioning its PP block at each specific feature level.
+  static const uint32_t kSDEPpVersionInvalid = 0;
+  static const uint32_t kSDEIgcV17 = 1;
+  static const uint32_t kSDEPgcV17 = 5;
+  static const uint32_t kSDEDitherV17 = 7;
+  static const uint32_t kSDEGamutV17 = 9;
+  static const uint32_t kSDEPaV17 = 11;
+  static const uint32_t kSDEPccV17 = 13;
+  static const uint32_t kSDELegacyPP = 15;
+  static const uint32_t kSDEPADitherV17 = 16;
+  static const uint32_t kSDEIgcV30 = 17;
+  static const uint32_t kSDEGamutV4 = 18;
+
+  uint32_t version[kMaxNumPPFeatures];
+  PPFeatureVersion() { memset(version, 0, sizeof(version)); }
+};
+
+struct PPHWAttributes : HWResourceInfo, HWPanelInfo, DisplayConfigVariableInfo {
+  char panel_name[256] = "generic_panel";
+  PPFeatureVersion version;
+  int panel_max_brightness = 0;
+
+  void Set(const HWResourceInfo &hw_res, const HWPanelInfo &panel_info,
+           const DisplayConfigVariableInfo &attr, const PPFeatureVersion &feature_ver);
+};
+
+struct PPDisplayAPIPayload {
+  bool own_payload = false;  // to indicate if *payload is owned by this or just a reference.
+  uint32_t size = 0;
+  uint8_t *payload = NULL;
+
+  PPDisplayAPIPayload() = default;
+  PPDisplayAPIPayload(uint32_t size, uint8_t *param)
+      : size(size), payload(param) {}
+
+  template <typename T>
+  DisplayError CreatePayload(T *&output) {
+    DisplayError ret = kErrorNone;
+
+    payload = new uint8_t[sizeof(T)]();
+    if (!payload) {
+      ret = kErrorMemory;
+      output = NULL;
+    } else {
+      this->size = sizeof(T);
+      output = reinterpret_cast<T *>(payload);
+      own_payload = true;
+    }
+    return ret;
+  }
+
+  DisplayError CreatePayloadBytes(uint32_t size_in_bytes, uint8_t **output) {
+    DisplayError ret = kErrorNone;
+
+    payload = new uint8_t[size_in_bytes]();
+    if (!payload) {
+      ret = kErrorMemory;
+      *output = NULL;
+    } else {
+      this->size = size_in_bytes;
+      *output = payload;
+      own_payload = true;
+    }
+    return ret;
+  }
+
+  inline void DestroyPayload() {
+    if (payload && own_payload) {
+      delete[] payload;
+      payload = NULL;
+      size = 0;
+    } else {
+      payload = NULL;
+      size = 0;
+    }
+  }
+};
+
+struct PPRectInfo {
+  uint32_t width;
+  uint32_t height;
+  int32_t x;
+  int32_t y;
+};
+
+typedef enum {
+  PP_PIXEL_FORMAT_NONE = 0,
+  PP_PIXEL_FORMAT_RGB_888,
+  PP_PIXEL_FORMAT_RGB_2101010,
+  PP_PIXEL_FORMAT_MAX,
+  PP_PIXEL_FORMAT_FORCE32BIT = 0x7FFFFFFF,
+} PPPixelFormats;
+
+struct PPFrameCaptureInputParams {
+  PPRectInfo rect;
+  PPPixelFormats out_pix_format;
+  uint32_t flags;
+};
+
+struct PPFrameCaptureData {
+  PPFrameCaptureInputParams input_params;
+  uint8_t *buffer;
+  uint32_t buffer_stride;
+  uint32_t buffer_size;
+};
+
+static const uint32_t kDeTuningFlagSharpFactor = 0x01;
+static const uint32_t kDeTuningFlagClip = 0x02;
+static const uint32_t kDeTuningFlagThrQuiet = 0x04;
+static const uint32_t kDeTuningFlagThrDieout = 0x08;
+static const uint32_t kDeTuningFlagThrLow = 0x10;
+static const uint32_t kDeTuningFlagThrHigh = 0x20;
+static const uint32_t kDeTuningFlagContentQualLevel = 0x40;
+
+typedef enum {
+  kDeContentQualUnknown,
+  kDeContentQualLow,
+  kDeContentQualMedium,
+  kDeContentQualHigh,
+  kDeContentQualMax,
+} PPDEContentQualLevel;
+
+typedef enum {
+  kDeContentTypeUnknown,
+  kDeContentTypeVideo,
+  kDeContentTypeGraphics,
+  kDeContentTypeMax,
+} PPDEContentType;
+
+struct PPDETuningCfg {
+  uint32_t flags = 0;
+  int32_t sharp_factor = 0;
+  uint16_t thr_quiet = 0;
+  uint16_t thr_dieout = 0;
+  uint16_t thr_low = 0;
+  uint16_t thr_high = 0;
+  uint16_t clip = 0;
+  PPDEContentQualLevel quality = kDeContentQualUnknown;
+  PPDEContentType content_type = kDeContentTypeUnknown;
+};
+
+struct PPDETuningCfgData {
+  uint32_t cfg_en = 0;
+  PPDETuningCfg params;
+  bool cfg_pending = false;
+};
+
+struct SDEGamutCfg {
+  static const int kGamutTableNum = 4;
+  static const int kGamutScaleoffTableNum = 3;
+  static const int kGamutTableSize = 1229;
+  static const int kGamutTableCoarseSize = 32;
+  static const int kGamutScaleoffSize = 16;
+  uint32_t mode;
+  uint32_t map_en;
+  uint32_t tbl_size[kGamutTableNum];
+  uint32_t *c0_data[kGamutTableNum];
+  uint32_t *c1_c2_data[kGamutTableNum];
+  uint32_t tbl_scale_off_sz[kGamutScaleoffTableNum];
+  uint32_t *scale_off_data[kGamutScaleoffTableNum];
+};
+
+struct SDEPccCoeff {
+  uint32_t c = 0;
+  uint32_t r = 0;
+  uint32_t g = 0;
+  uint32_t b = 0;
+  uint32_t rg = 0;
+  uint32_t gb = 0;
+  uint32_t rb = 0;
+  uint32_t rgb = 0;
+};
+
+struct SDEPccCfg {
+  SDEPccCoeff red;
+  SDEPccCoeff green;
+  SDEPccCoeff blue;
+
+  static SDEPccCfg *Init(uint32_t arg __attribute__((__unused__)));
+  SDEPccCfg *GetConfig() { return this; }
+};
+
+struct SDEDitherCfg {
+  uint32_t g_y_depth;
+  uint32_t r_cr_depth;
+  uint32_t b_cb_depth;
+  uint32_t length;
+  uint32_t dither_matrix[16];
+  uint32_t temporal_en;
+
+  static SDEDitherCfg *Init(uint32_t arg __attribute__((__unused__)));
+  SDEDitherCfg *GetConfig() { return this; }
+};
+
+struct SDEPADitherData {
+  uint64_t data_flags;
+  uint32_t matrix_size;
+  uint64_t matrix_data_addr;
+  uint32_t strength;
+  uint32_t offset_en;
+};
+
+class SDEPADitherWrapper : private SDEPADitherData {
+ public:
+  static SDEPADitherWrapper *Init(uint32_t arg __attribute__((__unused__)));
+  ~SDEPADitherWrapper() {
+    if (buffer_)
+      delete[] buffer_;
+  }
+  inline SDEPADitherData *GetConfig(void) { return this; }
+
+ private:
+  SDEPADitherWrapper() {}
+  uint32_t *buffer_ = NULL;
+};
+
+struct SDEPaMemColorData {
+  uint32_t adjust_p0 = 0;
+  uint32_t adjust_p1 = 0;
+  uint32_t adjust_p2 = 0;
+  uint32_t blend_gain = 0;
+  uint8_t sat_hold = 0;
+  uint8_t val_hold = 0;
+  uint32_t hue_region = 0;
+  uint32_t sat_region = 0;
+  uint32_t val_region = 0;
+};
+
+struct SDEPaData {
+  static const int kSixZoneLUTSize = 384;
+  uint32_t mode = 0;
+  uint32_t hue_adj = 0;
+  uint32_t sat_adj = 0;
+  uint32_t val_adj = 0;
+  uint32_t cont_adj;
+  SDEPaMemColorData skin;
+  SDEPaMemColorData sky;
+  SDEPaMemColorData foliage;
+  uint32_t six_zone_thresh = 0;
+  uint32_t six_zone_adj_p0 = 0;
+  uint32_t six_zone_adj_p1 = 0;
+  uint8_t six_zone_sat_hold = 0;
+  uint8_t six_zone_val_hold = 0;
+  uint32_t six_zone_len = 0;
+  uint32_t *six_zone_curve_p0 = NULL;
+  uint32_t *six_zone_curve_p1 = NULL;
+};
+
+struct SDEIgcLUTData {
+  static const int kMaxIgcLUTEntries = 256;
+  uint32_t table_fmt = 0;
+  uint32_t len = 0;
+  uint32_t *c0_c1_data = NULL;
+  uint32_t *c2_data = NULL;
+};
+
+struct SDEIgcV30LUTData {
+  static const int kMaxIgcLUTEntries = 256;
+  uint32_t table_fmt = 0;
+  uint32_t len = 0;
+  uint64_t c0_c1_data = 0;
+  uint64_t c2_data = 0;
+  uint32_t strength = 0;
+};
+
+struct SDEPgcLUTData {
+  static const int kPgcLUTEntries = 1024;
+  uint32_t len = 0;
+  uint32_t *c0_data = NULL;
+  uint32_t *c1_data = NULL;
+  uint32_t *c2_data = NULL;
+};
+
+struct SDEDisplayMode {
+  static const int kMaxModeNameSize = 256;
+  int32_t id = -1;
+  uint32_t type = 0;
+  char name[kMaxModeNameSize] = {0};
+};
+
+// Wrapper on HW block config data structure to encapsulate the details of allocating
+// and destroying from the caller.
+class SDEGamutCfgWrapper : private SDEGamutCfg {
+ public:
+  enum GamutMode {
+    GAMUT_FINE_MODE = 0x01,
+    GAMUT_COARSE_MODE,
+    GAMUT_COARSE_MODE_13,
+  };
+
+  // This factory method will be used by libsdm-color.so data producer to be populated with
+  // converted config values for SDE feature blocks.
+  static SDEGamutCfgWrapper *Init(uint32_t arg);
+
+  // Data consumer<Commit thread> will be responsible to destroy it once the feature is commited.
+  ~SDEGamutCfgWrapper() {
+    if (buffer_)
+      delete[] buffer_;
+  }
+
+  // Data consumer will use this method to retrieve contained feature configuration.
+  inline SDEGamutCfg *GetConfig(void) { return this; }
+
+ private:
+  SDEGamutCfgWrapper() {}
+  uint32_t *buffer_ = NULL;
+};
+
+class SDEPaCfgWrapper : private SDEPaData {
+ public:
+  static SDEPaCfgWrapper *Init(uint32_t arg = 0);
+  ~SDEPaCfgWrapper() {
+    if (buffer_)
+      delete[] buffer_;
+  }
+  inline SDEPaData *GetConfig(void) { return this; }
+
+ private:
+  SDEPaCfgWrapper() {}
+  uint32_t *buffer_ = NULL;
+};
+
+class SDEIgcLUTWrapper : private SDEIgcLUTData {
+ public:
+  static SDEIgcLUTWrapper *Init(uint32_t arg __attribute__((__unused__)));
+  ~SDEIgcLUTWrapper() {
+    if (buffer_)
+      delete[] buffer_;
+  }
+  inline SDEIgcLUTData *GetConfig(void) { return this; }
+
+ private:
+  SDEIgcLUTWrapper() {}
+  uint32_t *buffer_ = NULL;
+};
+
+class SDEIgcV30LUTWrapper : private SDEIgcV30LUTData {
+ public:
+  static SDEIgcV30LUTWrapper *Init(uint32_t arg __attribute__((__unused__)));
+  ~SDEIgcV30LUTWrapper() {
+    if (buffer_)
+      delete[] buffer_;
+  }
+  inline SDEIgcV30LUTData *GetConfig(void) { return this; }
+
+ private:
+  SDEIgcV30LUTWrapper(const SDEIgcV30LUTWrapper& src) { /* do not create copies */ }
+  SDEIgcV30LUTWrapper& operator=(const SDEIgcV30LUTWrapper&) { return *this; }
+  SDEIgcV30LUTWrapper() {}
+  uint32_t *buffer_ = NULL;
+};
+
+class SDEPgcLUTWrapper : private SDEPgcLUTData {
+ public:
+  static SDEPgcLUTWrapper *Init(uint32_t arg __attribute__((__unused__)));
+  ~SDEPgcLUTWrapper() {
+    if (buffer_)
+      delete[] buffer_;
+  }
+  inline SDEPgcLUTData *GetConfig(void) { return this; }
+
+ private:
+  SDEPgcLUTWrapper() {}
+  uint32_t *buffer_ = NULL;
+};
+
+// Base Postprocessing features information.
+class PPFeatureInfo {
+ public:
+  uint32_t enable_flags_ = 0;  // bitmap to indicate subset of parameters enabling or not.
+  uint32_t feature_version_ = 0;
+  uint32_t feature_id_ = 0;
+  uint32_t disp_id_ = 0;
+  uint32_t pipe_id_ = 0;
+
+  virtual ~PPFeatureInfo() {}
+  virtual void *GetConfigData(void) const = 0;
+};
+
+// Individual Postprocessing feature representing physical attributes and information
+// This template class wrapping around abstract data type representing different
+// post-processing features. It will take output from ColorManager converting from raw metadata.
+// The configuration will directly pass into HWInterface to program the hardware accordingly.
+template <typename T>
+class TPPFeatureInfo : public PPFeatureInfo {
+ public:
+  virtual ~TPPFeatureInfo() {
+    if (params_)
+      delete params_;
+  }
+
+  // API for data consumer to get underlying data configs to program into pp hardware block.
+  virtual void *GetConfigData(void) const { return params_->GetConfig(); }
+
+  // API for data producer to get access to underlying data configs to populate it.
+  T *GetParamsReference(void) { return params_; }
+
+  // API for create this template object.
+  static TPPFeatureInfo *Init(uint32_t arg = 0) {
+    TPPFeatureInfo *info = new TPPFeatureInfo();
+    if (info) {
+      info->params_ = T::Init(arg);
+      if (!info->params_) {
+        delete info;
+        info = NULL;
+      }
+    }
+
+    return info;
+  }
+
+ protected:
+  TPPFeatureInfo() = default;
+
+ private:
+  T *params_ = NULL;
+};
+
+// This singleton class serves as data exchanging central between data producer
+// <libsdm-color.so> and data consumer<SDM and HWC.>
+// This class defines PP pending features to be programmed, which generated from
+// ColorManager. Dirty flag indicates some features are available to be programmed.
+// () Lock is needed since the object wil be accessed from 2 tasks.
+// All API exposed are not threadsafe, it's caller's responsiblity to acquire the locker.
+class PPFeaturesConfig {
+ public:
+  PPFeaturesConfig() { memset(feature_, 0, sizeof(feature_)); }
+  ~PPFeaturesConfig() { Reset(); }
+
+  // ColorManager installs one TFeatureInfo<T> to take the output configs computed
+  // from ColorManager, containing all physical features to be programmed and also compute
+  // metadata/populate into T.
+  inline DisplayError AddFeature(uint32_t feature_id, PPFeatureInfo *feature) {
+    if (feature_id < kMaxNumPPFeatures)
+      feature_[feature_id] = feature;
+
+    return kErrorNone;
+  }
+
+  inline Locker &GetLocker(void) { return locker_; }
+  inline PPFrameCaptureData *GetFrameCaptureData(void) { return &frame_capture_data; }
+  inline PPDETuningCfgData *GetDETuningCfgData(void) { return &de_tuning_data_; }
+  // Once all features are consumed, destroy/release all TFeatureInfo<T> on the list,
+  // then clear dirty_ flag and return the lock to the TFeatureInfo<T> producer.
+  void Reset();
+
+  // Consumer to call this to retrieve all the TFeatureInfo<T> on the list to be programmed.
+  DisplayError RetrieveNextFeature(PPFeatureInfo **feature);
+
+  inline bool IsDirty() { return dirty_; }
+  inline void MarkAsDirty() { dirty_ = true; }
+
+ private:
+  bool dirty_ = 0;
+  Locker locker_;
+  PPFeatureInfo *feature_[kMaxNumPPFeatures];  // reference to TFeatureInfo<T>.
+  uint32_t next_idx_ = 0;
+  PPFrameCaptureData frame_capture_data;
+  PPDETuningCfgData de_tuning_data_;
+};
+
+}  // namespace sdm
+
+#endif  // __COLOR_PARAMS_H__
diff --git a/sdm845/sdm/include/private/dpps_control_interface.h b/sdm845/sdm/include/private/dpps_control_interface.h
new file mode 100644
index 0000000..8a44907
--- /dev/null
+++ b/sdm845/sdm/include/private/dpps_control_interface.h
@@ -0,0 +1,40 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DPPS_CONTROL_INTERFACE_H__
+#define __DPPS_CONTROL_INTERFACE_H__
+
+namespace sdm {
+
+class DppsControlInterface {
+ public:
+  virtual ~DppsControlInterface() { }
+  virtual DisplayError On() = 0;
+  virtual DisplayError Off() = 0;
+};
+
+}  // namespace sdm
+
+#endif  // __DPPS_CONTROL_INTERFACE_H__
+
diff --git a/sdm845/sdm/include/private/extension_interface.h b/sdm845/sdm/include/private/extension_interface.h
new file mode 100644
index 0000000..2e5bd49
--- /dev/null
+++ b/sdm845/sdm/include/private/extension_interface.h
@@ -0,0 +1,87 @@
+/*
+* Copyright (c) 2015 - 2017, 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 __EXTENSION_INTERFACE_H__
+#define __EXTENSION_INTERFACE_H__
+
+#include <core/sdm_types.h>
+#include <core/display_interface.h>
+
+#include "partial_update_interface.h"
+#include "strategy_interface.h"
+#include "resource_interface.h"
+#include "dpps_control_interface.h"
+
+namespace sdm {
+
+#define EXTENSION_LIBRARY_NAME "libsdmextension.so"
+#define CREATE_EXTENSION_INTERFACE_NAME "CreateExtensionInterface"
+#define DESTROY_EXTENSION_INTERFACE_NAME "DestroyExtensionInterface"
+
+#define EXTENSION_REVISION_MAJOR (1)
+#define EXTENSION_REVISION_MINOR (0)
+
+#define EXTENSION_VERSION_TAG ((uint16_t) ((EXTENSION_REVISION_MAJOR << 8) \
+                                          | EXTENSION_REVISION_MINOR))
+
+class ExtensionInterface;
+
+typedef DisplayError (*CreateExtensionInterface)(uint16_t version, ExtensionInterface **interface);
+typedef DisplayError (*DestroyExtensionInterface)(ExtensionInterface *interface);
+
+class ExtensionInterface {
+ public:
+  virtual DisplayError CreatePartialUpdate(DisplayType type, const HWResourceInfo &hw_resource_info,
+                                           const HWPanelInfo &hw_panel_info,
+                                           const HWMixerAttributes &mixer_attributes,
+                                           const HWDisplayAttributes &display_attributes,
+                                           const DisplayConfigVariableInfo &fb_config,
+                                           PartialUpdateInterface **interface) = 0;
+  virtual DisplayError DestroyPartialUpdate(PartialUpdateInterface *interface) = 0;
+
+  virtual DisplayError CreateStrategyExtn(DisplayType type, BufferAllocator *buffer_allocator,
+                                          const HWResourceInfo &hw_resource_info,
+                                          const HWPanelInfo &hw_panel_info,
+                                          const HWMixerAttributes &mixer_attributes,
+                                          const DisplayConfigVariableInfo &fb_config,
+                                          StrategyInterface **interface) = 0;
+  virtual DisplayError DestroyStrategyExtn(StrategyInterface *interface) = 0;
+
+  virtual DisplayError CreateResourceExtn(const HWResourceInfo &hw_resource_info,
+                                          BufferAllocator *buffer_allocator,
+                                          BufferSyncHandler *buffer_sync_handler,
+                                          ResourceInterface **interface) = 0;
+  virtual DisplayError DestroyResourceExtn(ResourceInterface *interface) = 0;
+  virtual DisplayError CreateDppsControlExtn(DppsControlInterface **dpps_control_interface,
+                                             SocketHandler *socket_handler) = 0;
+  virtual DisplayError DestroyDppsControlExtn(DppsControlInterface *interface) = 0;
+
+ protected:
+  virtual ~ExtensionInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __EXTENSION_INTERFACE_H__
+
diff --git a/sdm845/sdm/include/private/hw_info_types.h b/sdm845/sdm/include/private/hw_info_types.h
new file mode 100644
index 0000000..cdfec2e
--- /dev/null
+++ b/sdm845/sdm/include/private/hw_info_types.h
@@ -0,0 +1,568 @@
+/*
+* Copyright (c) 2015-2017, 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_TYPES_H__
+#define __HW_INFO_TYPES_H__
+
+#include <stdint.h>
+#include <core/display_interface.h>
+#include <core/core_interface.h>
+#include <vector>
+#include <map>
+#include <string>
+#include <bitset>
+
+namespace sdm {
+using std::string;
+
+const int kMaxSDELayers = 16;   // Maximum number of layers that can be handled by MDP5 hardware
+                                // in a given layer stack.
+const int kMaxBlitLayers = 32;   // Maximum number of layers that can be handled by MDP3 hardware
+                                // in a given layer stack.
+#define MAX_PLANES 4
+
+#define MAX_DETAIL_ENHANCE_CURVE 3
+
+enum HWDeviceType {
+  kDevicePrimary,
+  kDeviceHDMI,
+  kDeviceVirtual,
+  kDeviceRotator,
+  kDeviceMax,
+};
+
+enum HWBlockType {
+  kHWPrimary,
+  kHWHDMI,
+  kHWWriteback0,
+  kHWWriteback1,
+  kHWWriteback2,
+  kHWBlockMax
+};
+
+enum HWDisplayMode {
+  kModeDefault,
+  kModeVideo,
+  kModeCommand,
+};
+
+enum PipeType {
+  kPipeTypeUnused,
+  kPipeTypeVIG,
+  kPipeTypeRGB,
+  kPipeTypeDMA,
+  kPipeTypeCursor,
+};
+
+enum HWSubBlockType {
+  kHWVIGPipe,
+  kHWRGBPipe,
+  kHWDMAPipe,
+  kHWCursorPipe,
+  kHWRotatorInput,
+  kHWRotatorOutput,
+  kHWWBIntfOutput,
+  kHWDestinationScalar,
+  kHWSubBlockMax,
+};
+
+enum HWAlphaInterpolation {
+  kInterpolationPixelRepeat,
+  kInterpolationBilinear,
+  kInterpolationMax,
+};
+
+enum HWBlendingFilter {
+  kBlendFilterCircular,
+  kBlendFilterSeparable,
+  kBlendFilterMax,
+};
+
+enum HWPipeFlags {
+  kIGC = 0x01,
+  kMultiRect = 0x02,
+  kMultiRectParallelMode = 0x04,
+};
+
+enum HWAVRModes {
+  kContinuousMode,  // Mode to enable AVR feature for every frame.
+  kOneShotMode,     // Mode to enable AVR feature for particular frame.
+};
+
+typedef std::map<HWSubBlockType, std::vector<LayerBufferFormat>> FormatsMap;
+typedef std::map<LayerBufferFormat, float> CompRatioMap;
+
+struct HWDynBwLimitInfo {
+  uint32_t cur_mode = kBwDefault;
+  uint64_t total_bw_limit[kBwModeMax] = { 0 };
+  uint64_t pipe_bw_limit[kBwModeMax] = { 0 };
+};
+
+struct HWPipeCaps {
+  PipeType type = kPipeTypeUnused;
+  uint32_t id = 0;
+  uint32_t master_pipe_id = 0;
+  uint32_t max_rects = 1;
+};
+
+struct HWRotatorInfo {
+  enum { ROT_TYPE_MDSS, ROT_TYPE_V4L2 };
+  uint32_t type = ROT_TYPE_MDSS;
+  uint32_t num_rotator = 0;
+  bool has_downscale = false;
+  std::string device_path = "";
+  float min_downscale = 2.0f;
+  bool downscale_compression = false;
+
+  void Reset() { *this = HWRotatorInfo(); }
+};
+
+struct HWDestScalarInfo {
+  uint32_t count = 0;
+  uint32_t max_input_width = 0;
+  uint32_t max_output_width = 0;
+  uint32_t max_scale_up = 1;
+  uint32_t prefill_lines = 4;
+};
+
+enum SmartDMARevision {
+  V1,
+  V2,
+};
+
+struct HWResourceInfo {
+  uint32_t hw_version = 0;
+  uint32_t hw_revision = 0;
+  uint32_t num_dma_pipe = 0;
+  uint32_t num_vig_pipe = 0;
+  uint32_t num_rgb_pipe = 0;
+  uint32_t num_cursor_pipe = 0;
+  uint32_t num_blending_stages = 0;
+  uint32_t num_control = 0;
+  uint32_t num_mixer_to_disp = 0;
+  uint32_t smp_total = 0;
+  uint32_t smp_size = 0;
+  uint32_t num_smp_per_pipe = 0;
+  uint32_t max_scale_up = 1;
+  uint32_t max_scale_down = 1;
+  uint64_t max_bandwidth_low = 0;
+  uint64_t max_bandwidth_high = 0;
+  uint32_t max_mixer_width = 2048;
+  uint32_t max_pipe_width = 2048;
+  uint32_t max_cursor_size = 0;
+  uint64_t max_pipe_bw =  0;
+  uint32_t max_sde_clk = 0;
+  float clk_fudge_factor = 1.0f;
+  uint32_t macrotile_nv12_factor = 0;
+  uint32_t macrotile_factor = 0;
+  uint32_t linear_factor = 0;
+  uint32_t scale_factor = 0;
+  uint32_t extra_fudge_factor = 0;
+  uint32_t amortizable_threshold = 0;
+  uint32_t system_overhead_lines = 0;
+  bool has_bwc = false;
+  bool has_ubwc = false;
+  bool has_decimation = false;
+  bool has_macrotile = false;
+  bool has_non_scalar_rgb = false;
+  bool is_src_split = false;
+  bool has_dyn_bw_support = false;
+  bool separate_rotator = false;
+  bool has_qseed3 = false;
+  bool has_concurrent_writeback = false;
+  bool has_ppp = false;
+  uint32_t writeback_index = kHWBlockMax;
+  HWDynBwLimitInfo dyn_bw_info;
+  std::vector<HWPipeCaps> hw_pipes;
+  FormatsMap supported_formats_map;
+  HWRotatorInfo hw_rot_info;
+  HWDestScalarInfo hw_dest_scalar_info;
+  bool has_avr = false;
+  bool has_hdr = false;
+  SmartDMARevision smart_dma_rev = SmartDMARevision::V1;
+  float ib_fudge_factor = 1.0f;
+  uint32_t undersized_prefill_lines = 0;
+  CompRatioMap comp_ratio_rt_map;
+  CompRatioMap comp_ratio_nrt_map;
+
+  void Reset() { *this = HWResourceInfo(); }
+};
+
+struct HWSplitInfo {
+  uint32_t left_split = 0;
+  uint32_t right_split = 0;
+
+  bool operator !=(const HWSplitInfo &split_info) {
+    return ((left_split != split_info.left_split) || (right_split != split_info.right_split));
+  }
+
+  bool operator ==(const HWSplitInfo &split_info) {
+    return !(operator !=(split_info));
+  }
+};
+
+enum HWS3DMode {
+  kS3DModeNone,
+  kS3DModeLR,
+  kS3DModeRL,
+  kS3DModeTB,
+  kS3DModeFP,
+  kS3DModeMax,
+};
+
+struct HWColorPrimaries {
+  uint32_t white_point[2] = {};       // White point
+  uint32_t red[2] = {};               // Red color primary
+  uint32_t green[2] = {};             // Green color primary
+  uint32_t blue[2] = {};              // Blue color primary
+};
+
+struct HWPanelOrientation {
+  bool rotation = false;
+  bool flip_horizontal = false;
+  bool flip_vertical = false;
+};
+
+struct HWPanelInfo {
+  DisplayPort port = kPortDefault;    // Display port
+  HWDisplayMode mode = kModeDefault;  // Display mode
+  bool partial_update = false;        // Partial update feature
+  int left_align = 1;                 // ROI left alignment restriction
+  int width_align = 1;                // ROI width alignment restriction
+  int top_align = 1;                  // ROI top alignment restriction
+  int height_align = 1;               // ROI height alignment restriction
+  int min_roi_width = 1;              // Min width needed for ROI
+  int min_roi_height = 1;             // Min height needed for ROI
+  bool needs_roi_merge = false;       // Merge ROI's of both the DSI's
+  bool dynamic_fps = false;           // Panel Supports dynamic fps
+  bool dfps_porch_mode = false;       // dynamic fps VFP or HFP mode
+  bool ping_pong_split = false;       // Supports Ping pong split
+  uint32_t min_fps = 0;               // Min fps supported by panel
+  uint32_t max_fps = 0;               // Max fps supported by panel
+  bool is_primary_panel = false;      // Panel is primary display
+  bool is_pluggable = false;          // Panel is pluggable
+  HWSplitInfo split_info;             // Panel split configuration
+  char panel_name[256] = {0};         // Panel name
+  HWS3DMode s3d_mode = kS3DModeNone;  // Panel's current s3d mode.
+  int panel_max_brightness = 0;       // Max panel brightness
+  uint32_t left_roi_count = 1;        // Number if ROI supported on left panel
+  uint32_t right_roi_count = 1;       // Number if ROI supported on right panel
+  bool hdr_enabled = false;           // HDR feature supported
+  uint32_t peak_luminance = 0;        // Panel's peak luminance level
+  uint32_t average_luminance = 0;     // Panel's average luminance level
+  uint32_t blackness_level = 0;       // Panel's blackness level
+  HWColorPrimaries primaries = {};    // WRGB color primaries
+  HWPanelOrientation panel_orientation = {};  // Panel Orientation
+
+  bool operator !=(const HWPanelInfo &panel_info) {
+    return ((port != panel_info.port) || (mode != panel_info.mode) ||
+            (partial_update != panel_info.partial_update) ||
+            (left_align != panel_info.left_align) || (width_align != panel_info.width_align) ||
+            (top_align != panel_info.top_align) || (height_align != panel_info.height_align) ||
+            (min_roi_width != panel_info.min_roi_width) ||
+            (min_roi_height != panel_info.min_roi_height) ||
+            (needs_roi_merge != panel_info.needs_roi_merge) ||
+            (dynamic_fps != panel_info.dynamic_fps) || (min_fps != panel_info.min_fps) ||
+            (dfps_porch_mode != panel_info.dfps_porch_mode) ||
+            (ping_pong_split != panel_info.ping_pong_split) ||
+            (max_fps != panel_info.max_fps) || (is_primary_panel != panel_info.is_primary_panel) ||
+            (split_info != panel_info.split_info) || (s3d_mode != panel_info.s3d_mode) ||
+            (left_roi_count != panel_info.left_roi_count) ||
+            (right_roi_count != panel_info.right_roi_count));
+  }
+
+  bool operator ==(const HWPanelInfo &panel_info) {
+    return !(operator !=(panel_info));
+  }
+};
+
+struct HWSessionConfig {
+  LayerRect src_rect;
+  LayerRect dst_rect;
+  uint32_t buffer_count = 0;
+  bool secure = false;
+  uint32_t frame_rate = 0;
+  LayerTransform transform;
+  bool secure_camera = false;
+
+  bool operator==(const HWSessionConfig& config) const {
+    return (src_rect == config.src_rect &&
+            dst_rect == config.dst_rect &&
+            buffer_count == config.buffer_count &&
+            secure == config.secure &&
+            frame_rate == config.frame_rate &&
+            transform == config.transform &&
+            secure_camera == config.secure_camera);
+  }
+
+  bool operator!=(const HWSessionConfig& config) const {
+    return !operator==(config);
+  }
+};
+
+struct HWRotateInfo {
+  int pipe_id = -1;  // Not actual pipe id, but the relative DMA id
+  int writeback_id = -1;  // Writeback block id, but this is the same as DMA id
+  LayerRect src_roi;  // Source crop of each split
+  LayerRect dst_roi;  // Destination crop of each split
+  bool valid = false;
+  int rotate_id = -1;  // Actual rotator session id with driver
+
+  void Reset() { *this = HWRotateInfo(); }
+};
+
+struct HWRotatorSession {
+  HWRotateInfo hw_rotate_info[kMaxRotatePerLayer];
+  uint32_t hw_block_count = 0;  // number of rotator hw blocks used by rotator session
+  int session_id = -1;  // A handle with Session Manager
+  HWSessionConfig hw_session_config;
+  LayerBuffer input_buffer;  // Input to rotator
+  LayerBuffer output_buffer;  // Output of rotator, crop width and stride are same
+  float input_compression = 1.0f;
+  float output_compression = 1.0f;
+  bool is_buffer_cached = false;
+};
+
+struct HWScaleLutInfo {
+  uint32_t dir_lut_size = 0;
+  uint32_t cir_lut_size = 0;
+  uint32_t sep_lut_size = 0;
+  uint64_t dir_lut = 0;
+  uint64_t cir_lut = 0;
+  uint64_t sep_lut = 0;
+};
+
+struct HWDetailEnhanceData : DisplayDetailEnhancerData {
+  uint16_t prec_shift = 0;
+  int16_t adjust_a[MAX_DETAIL_ENHANCE_CURVE] = {0};
+  int16_t adjust_b[MAX_DETAIL_ENHANCE_CURVE] = {0};
+  int16_t adjust_c[MAX_DETAIL_ENHANCE_CURVE] = {0};
+};
+
+struct HWPixelExtension {
+  int32_t extension = 0;  // Number of pixels extension in left, right, top and bottom directions
+                          // for all color components. This pixel value for each color component
+                          // should be sum of fetch and repeat pixels.
+
+  int32_t overfetch = 0;  // Number of pixels need to be overfetched in left, right, top and bottom
+                          // directions from source image for scaling.
+
+  int32_t repeat = 0;     // Number of pixels need to be repeated in left, right, top and bottom
+                          // directions for scaling.
+};
+
+struct HWPlane {
+  int32_t init_phase_x = 0;
+  int32_t phase_step_x = 0;
+  int32_t init_phase_y = 0;
+  int32_t phase_step_y = 0;
+  HWPixelExtension left;
+  HWPixelExtension top;
+  HWPixelExtension right;
+  HWPixelExtension bottom;
+  uint32_t roi_width = 0;
+  int32_t preload_x = 0;
+  int32_t preload_y = 0;
+  uint32_t src_width = 0;
+  uint32_t src_height = 0;
+};
+
+struct HWScaleData {
+  struct enable {
+    uint8_t scale = 0;
+    uint8_t direction_detection = 0;
+    uint8_t detail_enhance = 0;
+  } enable;
+  uint32_t dst_width = 0;
+  uint32_t dst_height = 0;
+  HWPlane plane[MAX_PLANES];
+  // scale_v2_data fields
+  ScalingFilterConfig y_rgb_filter_cfg = kFilterEdgeDirected;
+  ScalingFilterConfig uv_filter_cfg = kFilterEdgeDirected;
+  HWAlphaInterpolation alpha_filter_cfg = kInterpolationPixelRepeat;
+  HWBlendingFilter blend_cfg = kBlendFilterCircular;
+
+  struct lut_flags {
+    uint8_t lut_swap = 0;
+    uint8_t lut_dir_wr = 0;
+    uint8_t lut_y_cir_wr = 0;
+    uint8_t lut_uv_cir_wr = 0;
+    uint8_t lut_y_sep_wr = 0;
+    uint8_t lut_uv_sep_wr = 0;
+  } lut_flag;
+
+  uint32_t dir_lut_idx = 0;
+  /* for Y(RGB) and UV planes*/
+  uint32_t y_rgb_cir_lut_idx = 0;
+  uint32_t uv_cir_lut_idx = 0;
+  uint32_t y_rgb_sep_lut_idx = 0;
+  uint32_t uv_sep_lut_idx = 0;
+
+  HWDetailEnhanceData detail_enhance;
+};
+
+struct HWDestScaleInfo {
+  uint32_t mixer_width = 0;
+  uint32_t mixer_height = 0;
+  bool scale_update = false;
+  HWScaleData scale_data = {};
+  LayerRect panel_roi = {};
+};
+
+typedef std::map<uint32_t, HWDestScaleInfo *> DestScaleInfoMap;
+
+struct HWAVRInfo {
+  bool enable = false;                // Flag to Enable AVR feature
+  HWAVRModes mode = kContinuousMode;  // Specifies the AVR mode
+};
+
+struct HWPipeInfo {
+  HWPipeInfo *pair = NULL;
+  uint8_t rect = 255;
+  uint32_t pipe_id = 0;
+  HWSubBlockType sub_block_type = kHWSubBlockMax;
+  LayerRect src_roi;
+  LayerRect dst_roi;
+  uint8_t horizontal_decimation = 0;
+  uint8_t vertical_decimation = 0;
+  HWScaleData scale_data;
+  uint32_t z_order = 0;
+  uint8_t flags = 0;
+  bool valid = false;
+
+  void Reset() { *this = HWPipeInfo(); }
+};
+
+struct HWLayerConfig {
+  HWPipeInfo left_pipe;           // pipe for left side of output
+  HWPipeInfo right_pipe;          // pipe for right side of output
+  HWRotatorSession hw_rotator_session;
+  float compression = 1.0f;
+
+  void Reset() { *this = HWLayerConfig(); }
+};
+
+struct HWHDRLayerInfo {
+  enum HDROperation {
+    kNoOp,   // No-op.
+    kSet,    // Sets the HDR MetaData - Start of HDR
+    kReset,  // resets the previously set HDR Metadata, End of HDR
+  };
+
+  int32_t layer_index = -1;
+  HDROperation operation = kNoOp;
+};
+
+struct HWLayersInfo {
+  LayerStack *stack = NULL;        // Input layer stack. Set by the caller.
+  uint32_t app_layer_count = 0;    // Total number of app layers. Must not be 0.
+  uint32_t gpu_target_index = 0;   // GPU target layer index. 0 if not present.
+
+  std::vector<Layer> hw_layers = {};  // Layers which need to be programmed on the HW
+
+  uint32_t index[kMaxSDELayers] = {};   // Indexes of the layers from the layer stack which need to
+                                        // be programmed on hardware.
+  uint32_t roi_index[kMaxSDELayers] = {0};  // Stores the ROI index where the layers are visible.
+
+  int sync_handle = -1;         // Release fence id for current draw cycle.
+  int set_idle_time_ms = -1;    // Set idle time to the new specified value.
+                                //    -1 indicates no change in idle time since last set value.
+
+  std::vector<LayerRect> left_frame_roi = {};   // Left ROI.
+  std::vector<LayerRect> right_frame_roi = {};  // Right ROI.
+  LayerRect partial_fb_roi = {};   // Damaged area in framebuffer.
+  bool roi_split = false;          // Indicates separated left and right ROI
+  bool async_cursor_updates = false;  // Cursor layer allowed to have async updates
+  DestScaleInfoMap dest_scale_info_map = {};
+  HWHDRLayerInfo hdr_layer_info = {};
+  Handle pvt_data = NULL;   // Private data used by sdm extension only.
+};
+
+struct HWLayers {
+  HWLayersInfo info;
+  HWLayerConfig config[kMaxSDELayers];
+  float output_compression = 1.0f;
+  uint64_t ab_bps = 0;
+  uint64_t ib_bps = 0;
+  uint32_t clock_hz = 0;
+  HWAVRInfo hw_avr_info = {};
+};
+
+struct HWDisplayAttributes : DisplayConfigVariableInfo {
+  bool is_device_split = false;
+  uint32_t v_front_porch = 0;  //!< Vertical front porch of panel
+  uint32_t v_back_porch = 0;   //!< Vertical back porch of panel
+  uint32_t v_pulse_width = 0;  //!< Vertical pulse width of panel
+  uint32_t h_total = 0;        //!< Total width of panel (hActive + hFP + hBP + hPulseWidth)
+  uint32_t v_total = 0;        //!< Total height of panel (vActive + vFP + vBP + vPulseWidth)
+  std::bitset<32> s3d_config;  //!< Stores the bit mask of S3D modes
+
+  void Reset() { *this = HWDisplayAttributes(); }
+
+  bool operator !=(const HWDisplayAttributes &display_attributes) {
+    return ((is_device_split != display_attributes.is_device_split) ||
+            (x_pixels != display_attributes.x_pixels) ||
+            (y_pixels != display_attributes.y_pixels) ||
+            (x_dpi != display_attributes.x_dpi) ||
+            (y_dpi != display_attributes.y_dpi) ||
+            (fps != display_attributes.fps) ||
+            (vsync_period_ns != display_attributes.vsync_period_ns) ||
+            (v_front_porch != display_attributes.v_front_porch) ||
+            (v_back_porch != display_attributes.v_back_porch) ||
+            (v_pulse_width != display_attributes.v_pulse_width) ||
+            (h_total != display_attributes.h_total) ||
+            (is_yuv != display_attributes.is_yuv));
+  }
+
+  bool operator ==(const HWDisplayAttributes &display_attributes) {
+    return !(operator !=(display_attributes));
+  }
+};
+
+struct HWMixerAttributes {
+  uint32_t width = 0;                                  // Layer mixer width
+  uint32_t height = 0;                                 // Layer mixer height
+  uint32_t split_left = 0;
+  LayerBufferFormat output_format = kFormatRGB101010;  // Layer mixer output format
+
+  bool operator !=(const HWMixerAttributes &mixer_attributes) {
+    return ((width != mixer_attributes.width) ||
+            (height != mixer_attributes.height) ||
+            (output_format != mixer_attributes.output_format) ||
+            (split_left != mixer_attributes.split_left));
+  }
+
+  bool operator ==(const HWMixerAttributes &mixer_attributes) {
+    return !(operator !=(mixer_attributes));
+  }
+
+  bool IsValid() {
+    return (width > 0 && height > 0);
+  }
+};
+
+}  // namespace sdm
+
+#endif  // __HW_INFO_TYPES_H__
+
diff --git a/sdm845/sdm/include/private/partial_update_interface.h b/sdm845/sdm/include/private/partial_update_interface.h
new file mode 100644
index 0000000..a1c2382
--- /dev/null
+++ b/sdm845/sdm/include/private/partial_update_interface.h
@@ -0,0 +1,53 @@
+/*
+* 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 __PARTIAL_UPDATE_INTERFACE_H__
+#define __PARTIAL_UPDATE_INTERFACE_H__
+
+#include <core/display_interface.h>
+#include <core/buffer_allocator.h>
+#include <core/buffer_sync_handler.h>
+
+#include "hw_info_types.h"
+
+namespace sdm {
+
+struct PUConstraints {
+  bool enable = true;             //!< If this is set, PU will be enabled or it will be disabled
+};
+
+class PartialUpdateInterface {
+ public:
+  virtual DisplayError Start(const PUConstraints &pu_constraints) = 0;
+  virtual DisplayError GenerateROI(HWLayersInfo *hw_layers_info) = 0;
+  virtual DisplayError Stop() = 0;
+
+ protected:
+  virtual ~PartialUpdateInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __PARTIAL_UPDATE_INTERFACE_H__
+
diff --git a/sdm845/sdm/include/private/resource_interface.h b/sdm845/sdm/include/private/resource_interface.h
new file mode 100644
index 0000000..e140c33
--- /dev/null
+++ b/sdm845/sdm/include/private/resource_interface.h
@@ -0,0 +1,74 @@
+/*
+* Copyright (c) 2015 - 2017, 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_INTERFACE_H__
+#define __RESOURCE_INTERFACE_H__
+
+#include <core/display_interface.h>
+#include "hw_info_types.h"
+
+namespace sdm {
+
+class ResourceInterface {
+ public:
+  enum ResourceCmd {
+    kCmdResetScalarLUT,
+    kCmdMax,
+  };
+
+  virtual DisplayError RegisterDisplay(DisplayType type,
+                                       const HWDisplayAttributes &display_attributes,
+                                       const HWPanelInfo &hw_panel_info,
+                                       const HWMixerAttributes &mixer_attributes,
+                                       Handle *display_ctx) = 0;
+  virtual DisplayError UnregisterDisplay(Handle display_ctx) = 0;
+  virtual DisplayError ReconfigureDisplay(Handle display_ctx,
+                                          const HWDisplayAttributes &display_attributes,
+                                          const HWPanelInfo &hw_panel_info,
+                                          const HWMixerAttributes &mixer_attributes) = 0;
+  virtual DisplayError Start(Handle display_ctx) = 0;
+  virtual DisplayError Stop(Handle display_ctx) = 0;
+  virtual DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers) = 0;
+  virtual DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers) = 0;
+  virtual DisplayError Commit(Handle display_ctx, HWLayers *hw_layers) = 0;
+  virtual DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers) = 0;
+  virtual void Purge(Handle display_ctx) = 0;
+  virtual DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) = 0;
+  virtual DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst,
+                                       bool rotate90, BufferLayout layout,
+                                       bool use_rotator_downscale) = 0;
+  virtual DisplayError ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers,
+                                              int x, int y) = 0;
+  virtual DisplayError SetMaxBandwidthMode(HWBwModes mode) = 0;
+  virtual DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info) = 0;
+  virtual DisplayError SetDetailEnhancerData(Handle display_ctx,
+                                             const DisplayDetailEnhancerData &de_data) = 0;
+  virtual DisplayError Perform(int cmd, ...) = 0;
+  virtual ~ResourceInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __RESOURCE_INTERFACE_H__
+
diff --git a/sdm845/sdm/include/private/strategy_interface.h b/sdm845/sdm/include/private/strategy_interface.h
new file mode 100644
index 0000000..1174e7f
--- /dev/null
+++ b/sdm845/sdm/include/private/strategy_interface.h
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2014 - 2017, 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_INTERFACE_H__
+#define __STRATEGY_INTERFACE_H__
+
+#include <core/sdm_types.h>
+#include <core/display_interface.h>
+#include "hw_info_types.h"
+
+namespace sdm {
+
+struct StrategyConstraints {
+  bool safe_mode = false;   //!< In this mode, strategy manager chooses the composition strategy
+                            //!< that requires minimum number of pipe for the current frame. i.e.,
+                            //!< video only composition, secure only composition or GPU composition
+
+  uint32_t max_layers = kMaxSDELayers;  //!< Maximum number of layers that shall be programmed
+                                        //!< on hardware for the given layer stack.
+};
+
+class StrategyInterface {
+ public:
+  virtual DisplayError Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts) = 0;
+  virtual DisplayError GetNextStrategy(StrategyConstraints *constraints) = 0;
+  virtual DisplayError Stop() = 0;
+  virtual DisplayError Reconfigure(const HWPanelInfo &hw_panel_info,
+                                   const HWResourceInfo &hw_res_info,
+                                   const HWMixerAttributes &mixer_attributes,
+                                   const DisplayConfigVariableInfo &fb_config) = 0;
+  virtual DisplayError SetCompositionState(LayerComposition composition_type, bool enable) = 0;
+  virtual DisplayError Purge() = 0;
+  virtual DisplayError SetIdleTimeoutMs(uint32_t active_ms) = 0;
+
+  virtual ~StrategyInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __STRATEGY_INTERFACE_H__
+
diff --git a/sdm845/sdm/include/utils/constants.h b/sdm845/sdm/include/utils/constants.h
new file mode 100644
index 0000000..5efe357
--- /dev/null
+++ b/sdm845/sdm/include/utils/constants.h
@@ -0,0 +1,84 @@
+/*
+* Copyright (c) 2014 - 2017, 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 __CONSTANTS_H__
+#define __CONSTANTS_H__
+
+#include <stdlib.h>
+#include <inttypes.h>
+
+#ifndef PRIu64
+#define PRIu64 "llu"
+#endif
+
+#define INT(exp) static_cast<int>(exp)
+#define FLOAT(exp) static_cast<float>(exp)
+#define UINT8(exp) static_cast<uint8_t>(exp)
+#define UINT16(exp) static_cast<uint16_t>(exp)
+#define UINT32(exp) static_cast<uint32_t>(exp)
+#define INT32(exp) static_cast<int32_t>(exp)
+#define UINT64(exp) static_cast<uint64_t>(exp)
+
+#define ROUND_UP(number, step) ((((number) + ((step) - 1)) / (step)) * (step))
+
+#define BITMAP(bit) (1 << (bit))
+
+#define ROUND_UP_ALIGN_DOWN(value, a) FLOAT(FloorToMultipleOf(UINT32(value + 0.5f), UINT32(a)))
+#define ROUND_UP_ALIGN_UP(value, a) FLOAT(CeilToMultipleOf(UINT32(value + 0.5f), UINT32(a)))
+
+#define IDLE_TIMEOUT_DEFAULT_MS 70
+#define IDLE_TIMEOUT_ACTIVE_MS IDLE_TIMEOUT_DEFAULT_MS
+#define IDLE_TIMEOUT_INACTIVE_MS 520
+
+#define IS_RGB_FORMAT(format) (((format) < kFormatYCbCr420Planar) ? true: false)
+
+#define BITS_PER_BYTE 8
+#define BITS_TO_BYTES(x) (((x) + (BITS_PER_BYTE - 1)) / (BITS_PER_BYTE))
+
+// factor value should be in powers of 2(eg: 1, 2, 4, 8)
+template <class T1, class T2>
+inline T1 FloorToMultipleOf(const T1 &value, const T2 &factor) {
+  return (T1)(value & (~(factor - 1)));
+}
+
+template <class T1, class T2>
+inline T1 CeilToMultipleOf(const T1 &value, const T2 &factor) {
+  return (T1)((value + (factor - 1)) & (~(factor - 1)));
+}
+
+namespace sdm {
+
+  const int kThreadPriorityUrgent = -9;
+  const int kMaxRotatePerLayer = 2;
+  const uint32_t kMaxBlitTargetLayers = 2;
+  const int kPageSize = 4096;
+  const uint32_t kGridSize = 129;  // size used for non-linear transformation before Tone-mapping
+  const uint32_t kLutDim = 17;  // Dim of the 3d LUT for tone-mapping.
+
+  typedef void * Handle;
+
+}  // namespace sdm
+
+#endif  // __CONSTANTS_H__
+
diff --git a/sdm845/sdm/include/utils/debug.h b/sdm845/sdm/include/utils/debug.h
new file mode 100644
index 0000000..6f895c7
--- /dev/null
+++ b/sdm845/sdm/include/utils/debug.h
@@ -0,0 +1,120 @@
+/*
+* Copyright (c) 2014 - 2017, 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 __DEBUG_H__
+#define __DEBUG_H__
+
+#include <stdint.h>
+#include <core/sdm_types.h>
+#include <core/debug_interface.h>
+#include <core/display_interface.h>
+
+#define DLOG(tag, method, format, ...) Debug::Get()->method(tag, __CLASS__ "::%s: " format, \
+                                                            __FUNCTION__, ##__VA_ARGS__)
+
+#define DLOGE_IF(tag, format, ...) DLOG(tag, Error, format, ##__VA_ARGS__)
+#define DLOGW_IF(tag, format, ...) DLOG(tag, Warning, format, ##__VA_ARGS__)
+#define DLOGI_IF(tag, format, ...) DLOG(tag, Info, format, ##__VA_ARGS__)
+#define DLOGD_IF(tag, format, ...) DLOG(tag, Debug, format, ##__VA_ARGS__)
+#define DLOGV_IF(tag, format, ...) DLOG(tag, Verbose, format, ##__VA_ARGS__)
+
+#define DLOGE(format, ...) DLOGE_IF(kTagNone, format, ##__VA_ARGS__)
+#define DLOGD(format, ...) DLOGD_IF(kTagNone, format, ##__VA_ARGS__)
+#define DLOGW(format, ...) DLOGW_IF(kTagNone, format, ##__VA_ARGS__)
+#define DLOGI(format, ...) DLOGI_IF(kTagNone, format, ##__VA_ARGS__)
+#define DLOGV(format, ...) DLOGV_IF(kTagNone, format, ##__VA_ARGS__)
+
+#define DTRACE_BEGIN(custom_string) Debug::Get()->BeginTrace(__CLASS__, __FUNCTION__, custom_string)
+#define DTRACE_END() Debug::Get()->EndTrace()
+#define DTRACE_SCOPED() ScopeTracer <Debug> scope_tracer(__CLASS__, __FUNCTION__)
+
+namespace sdm {
+
+class Debug {
+ public:
+  static inline void SetDebugHandler(DebugHandler *debug_handler) {
+    debug_.debug_handler_ = debug_handler;
+  }
+  static inline DebugHandler* Get() { return debug_.debug_handler_; }
+  static int GetSimulationFlag();
+  static int GetHDMIResolution();
+  static void GetIdleTimeoutMs(uint32_t *active_ms, uint32_t *inactive_ms);
+  static int GetBootAnimLayerCount();
+  static bool IsRotatorDownScaleDisabled();
+  static bool IsDecimationDisabled();
+  static int GetMaxPipesPerMixer(DisplayType display_type);
+  static int GetMaxUpscale();
+  static bool IsVideoModeEnabled();
+  static bool IsRotatorUbwcDisabled();
+  static bool IsRotatorSplitDisabled();
+  static bool IsScalarDisabled();
+  static bool IsUbwcTiledFrameBuffer();
+  static bool IsAVRDisabled();
+  static bool IsExtAnimDisabled();
+  static bool IsPartialSplitDisabled();
+  static DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+  static int GetExtMaxlayers();
+  static bool GetProperty(const char *property_name, char *value);
+  static bool SetProperty(const char *property_name, const char *value);
+
+ private:
+  Debug();
+
+  // By default, drop any log messages/traces coming from Display manager. It will be overriden by
+  // Display manager client when core is successfully initialized.
+  class DefaultDebugHandler : public DebugHandler {
+   public:
+    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 Debug(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() { }
+    virtual DisplayError GetProperty(const char */*property_name*/, int */*value*/) {
+      return kErrorNotSupported;
+    }
+    virtual DisplayError GetProperty(const char */*property_name*/, char */*value*/) {
+      return kErrorNotSupported;
+    }
+    virtual DisplayError SetProperty(const char */*property_name*/, const char */*value*/) {
+      return kErrorNotSupported;
+    }
+  };
+
+  DefaultDebugHandler default_debug_handler_;
+  DebugHandler *debug_handler_;
+  static Debug debug_;
+};
+
+}  // namespace sdm
+
+#endif  // __DEBUG_H__
+
diff --git a/sdm845/sdm/include/utils/factory.h b/sdm845/sdm/include/utils/factory.h
new file mode 100644
index 0000000..f77a299
--- /dev/null
+++ b/sdm845/sdm/include/utils/factory.h
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2017, 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 __FACTORY_H__
+#define __FACTORY_H__
+
+#include <utility>
+#include <map>
+#include <string>
+
+namespace sdm {
+
+template <class Creator>
+class Factory {
+ public:
+  int Add(const std::string &name, const Creator &creator) {
+    map_.insert(std::pair<std::string, Creator>(name, creator));
+
+    return 0;
+  }
+
+  Creator Get(const std::string &name) {
+    typename std::map<std::string, Creator>::iterator it = map_.find(name);
+    if (it != map_.end()) {
+      return it->second;
+    }
+
+    return nullptr;
+  }
+
+ private:
+  std::map<std::string, Creator> map_;
+};
+
+}  // namespace sdm
+
+#endif  // __FACTORY_H__
diff --git a/sdm845/sdm/include/utils/formats.h b/sdm845/sdm/include/utils/formats.h
new file mode 100644
index 0000000..dd819dc
--- /dev/null
+++ b/sdm845/sdm/include/utils/formats.h
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*   * Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   * Redistributions in binary form must reproduce the above
+*     copyright notice, this list of conditions and the following
+*     disclaimer in the documentation and/or other materials provided
+*     with the distribution.
+*   * Neither the name of The Linux Foundation nor the names of its
+*     contributors may be used to endorse or promote products derived
+*     from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __FORMATS_H__
+#define __FORMATS_H__
+
+#include <core/layer_stack.h>
+
+namespace sdm {
+
+bool IsUBWCFormat(LayerBufferFormat format);
+bool Is10BitFormat(LayerBufferFormat format);
+const char *GetFormatString(const LayerBufferFormat &format);
+BufferLayout GetBufferLayout(LayerBufferFormat format);
+
+}  // namespace sdm
+
+#endif  // __FORMATS_H__
+
diff --git a/sdm845/sdm/include/utils/locker.h b/sdm845/sdm/include/utils/locker.h
new file mode 100644
index 0000000..0096098
--- /dev/null
+++ b/sdm845/sdm/include/utils/locker.h
@@ -0,0 +1,166 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __LOCKER_H__
+#define __LOCKER_H__
+
+#include <stdint.h>
+#include <pthread.h>
+#include <sys/time.h>
+
+#define SCOPE_LOCK(locker) Locker::ScopeLock lock(locker)
+#define SEQUENCE_ENTRY_SCOPE_LOCK(locker) Locker::SequenceEntryScopeLock lock(locker)
+#define SEQUENCE_EXIT_SCOPE_LOCK(locker) Locker::SequenceExitScopeLock lock(locker)
+#define SEQUENCE_WAIT_SCOPE_LOCK(locker) Locker::SequenceWaitScopeLock lock(locker)
+#define SEQUENCE_CANCEL_SCOPE_LOCK(locker) Locker::SequenceCancelScopeLock lock(locker)
+
+namespace sdm {
+
+class Locker {
+ public:
+  class ScopeLock {
+   public:
+    explicit ScopeLock(Locker& locker) : locker_(locker) {
+      locker_.Lock();
+    }
+
+    ~ScopeLock() {
+      locker_.Unlock();
+    }
+
+   private:
+    Locker &locker_;
+  };
+
+  class SequenceEntryScopeLock {
+   public:
+    explicit SequenceEntryScopeLock(Locker& locker) : locker_(locker) {
+      locker_.Lock();
+      locker_.sequence_wait_ = 1;
+    }
+
+    ~SequenceEntryScopeLock() {
+      locker_.Unlock();
+    }
+
+   private:
+    Locker &locker_;
+  };
+
+  class SequenceExitScopeLock {
+   public:
+    explicit SequenceExitScopeLock(Locker& locker) : locker_(locker) {
+      locker_.Lock();
+      locker_.sequence_wait_ = 0;
+    }
+
+    ~SequenceExitScopeLock() {
+      locker_.Broadcast();
+      locker_.Unlock();
+    }
+
+   private:
+    Locker &locker_;
+  };
+
+  class SequenceWaitScopeLock {
+   public:
+    explicit SequenceWaitScopeLock(Locker& locker) : locker_(locker), error_(false) {
+      locker_.Lock();
+
+      while (locker_.sequence_wait_ == 1) {
+        locker_.Wait();
+        error_ = (locker_.sequence_wait_ == -1);
+      }
+    }
+
+    ~SequenceWaitScopeLock() {
+      locker_.Unlock();
+    }
+
+    bool IsError() {
+      return error_;
+    }
+
+   private:
+    Locker &locker_;
+    bool error_;
+  };
+
+  class SequenceCancelScopeLock {
+   public:
+    explicit SequenceCancelScopeLock(Locker& locker) : locker_(locker) {
+      locker_.Lock();
+      locker_.sequence_wait_ = -1;
+    }
+
+    ~SequenceCancelScopeLock() {
+      locker_.Broadcast();
+      locker_.Unlock();
+    }
+
+   private:
+    Locker &locker_;
+  };
+
+  Locker() : sequence_wait_(0) {
+    pthread_mutex_init(&mutex_, 0);
+    pthread_cond_init(&condition_, 0);
+  }
+
+  ~Locker() {
+    pthread_mutex_destroy(&mutex_);
+    pthread_cond_destroy(&condition_);
+  }
+
+  void Lock() { pthread_mutex_lock(&mutex_); }
+  void Unlock() { pthread_mutex_unlock(&mutex_); }
+  void Signal() { pthread_cond_signal(&condition_); }
+  void Broadcast() { pthread_cond_broadcast(&condition_); }
+  void Wait() { pthread_cond_wait(&condition_, &mutex_); }
+  int WaitFinite(int ms) {
+    struct timespec ts;
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    ts.tv_sec = tv.tv_sec + ms/1000;
+    ts.tv_nsec = tv.tv_usec*1000 + (ms%1000)*1000000;
+    ts.tv_sec += ts.tv_nsec/1000000000L;
+    ts.tv_nsec %= 1000000000L;
+    return pthread_cond_timedwait(&condition_, &mutex_, &ts);
+  }
+
+ private:
+  pthread_mutex_t mutex_;
+  pthread_cond_t condition_;
+  int sequence_wait_;   // This flag is set to 1 on sequence entry, 0 on exit, and -1 on cancel.
+                        // Some routines will wait for sequence of function calls to finish
+                        // so that capturing a transitionary snapshot of context is prevented.
+                        // If flag is set to -1, these routines will exit without doing any
+                        // further processing.
+};
+
+}  // namespace sdm
+
+#endif  // __LOCKER_H__
+
diff --git a/sdm845/sdm/include/utils/rect.h b/sdm845/sdm/include/utils/rect.h
new file mode 100644
index 0000000..ea6edfb
--- /dev/null
+++ b/sdm845/sdm/include/utils/rect.h
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2015-2017, 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 __RECT_H__
+#define __RECT_H__
+
+#include <stdint.h>
+#include <core/sdm_types.h>
+#include <core/layer_stack.h>
+#include <utils/debug.h>
+
+namespace sdm {
+
+  enum RectOrientation {
+    kOrientationPortrait,
+    kOrientationLandscape,
+    kOrientationUnknown,
+  };
+
+  bool IsValid(const LayerRect &rect);
+  bool IsCongruent(const LayerRect &rect1, const LayerRect &rect2);
+  void Log(DebugTag debug_tag, const char *prefix, const LayerRect &roi);
+  void Normalize(const uint32_t &align_x, const uint32_t &align_y, LayerRect *rect);
+  LayerRect Union(const LayerRect &rect1, const LayerRect &rect2);
+  LayerRect Intersection(const LayerRect &rect1, const LayerRect &rect2);
+  LayerRect Subtract(const LayerRect &rect1, const LayerRect &rect2);
+  LayerRect Reposition(const LayerRect &rect1, const int &x_offset, const int &y_offset);
+  void SplitLeftRight(const LayerRect &in_rect, uint32_t split_count, uint32_t align_x,
+                      bool flip_horizontal, LayerRect *out_rects);
+  void SplitTopBottom(const LayerRect &in_rect, uint32_t split_count, uint32_t align_y,
+                      bool flip_horizontal, LayerRect *out_rects);
+  void MapRect(const LayerRect &src_domain, const LayerRect &dst_domain, const LayerRect &in_rect,
+               LayerRect *out_rect);
+  void TransformHV(const LayerRect &src_domain, const LayerRect &in_rect,
+                   const LayerTransform &transform, LayerRect *out_rect);
+  RectOrientation GetOrientation(const LayerRect &in_rect);
+}  // namespace sdm
+
+#endif  // __RECT_H__
+
diff --git a/sdm845/sdm/include/utils/sys.h b/sdm845/sdm/include/utils/sys.h
new file mode 100644
index 0000000..6b40df4
--- /dev/null
+++ b/sdm845/sdm/include/utils/sys.h
@@ -0,0 +1,101 @@
+/*
+* 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 __SYS_H__
+#define __SYS_H__
+
+#include <sys/eventfd.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <poll.h>
+#include <pthread.h>
+#include <fstream>
+
+#ifdef SDM_VIRTUAL_DRIVER
+#include <virtual_driver.h>
+#endif
+
+namespace sdm {
+
+class Sys {
+ public:
+#ifndef SDM_VIRTUAL_DRIVER
+  typedef std::fstream fstream;
+#else
+  typedef VirtualFStream fstream;
+#endif
+
+  // Pointers to system calls which are either mapped to actual system call or virtual driver.
+#ifdef TARGET_HEADLESS
+  typedef int (*ioctl)(int, unsigned long int, ...);  // NOLINT
+#else
+  typedef int (*ioctl)(int, int, ...);
+#endif
+  typedef int (*access)(const char *, int);
+  typedef int (*open)(const char *, int, ...);
+  typedef int (*close)(int);
+  typedef int (*poll)(struct pollfd *, nfds_t, int);
+  typedef ssize_t (*pread)(int, void *, size_t, off_t);
+  typedef ssize_t (*pwrite)(int, const void *, size_t, off_t);
+  typedef int (*pthread_cancel)(pthread_t thread);
+  typedef int (*dup)(int fd);
+  typedef ssize_t (*read)(int, void *, size_t);
+  typedef ssize_t (*write)(int, const void *, size_t);
+  typedef int (*eventfd)(unsigned int, int);
+
+  static bool getline_(fstream &fs, std::string &line);  // NOLINT
+
+  static ioctl ioctl_;
+  static access access_;
+  static open open_;
+  static close close_;
+  static poll poll_;
+  static pread pread_;
+  static pwrite pwrite_;
+  static pthread_cancel pthread_cancel_;
+  static dup dup_;
+  static read read_;
+  static write write_;
+  static eventfd eventfd_;
+};
+
+class DynLib {
+ public:
+  ~DynLib();
+  bool Open(const char *lib_name);
+  bool Sym(const char *func_name, void **func_ptr);
+  const char * Error() { return ::dlerror(); }
+  operator bool() const { return lib_ != NULL; }
+
+ private:
+  void Close();
+
+  void *lib_ = NULL;
+};
+
+}  // namespace sdm
+
+#endif  // __SYS_H__
diff --git a/sdm845/sdm/include/utils/utils.h b/sdm845/sdm/include/utils/utils.h
new file mode 100644
index 0000000..b1c55c4
--- /dev/null
+++ b/sdm845/sdm/include/utils/utils.h
@@ -0,0 +1,49 @@
+/*
+* Copyright (c) 2016 - 2017, 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 __UTILS_H__
+#define __UTILS_H__
+
+namespace sdm {
+
+float gcd(float a, float b);
+float lcm(float a, float b);
+void CloseFd(int *fd);
+
+enum class DriverType {
+    FB = 0,
+    DRM,
+};
+
+DriverType GetDriverType();
+
+}  // namespace sdm
+
+#endif  // __UTILS_H__
+
diff --git a/sdm845/sdm/libs/core/Android.mk b/sdm845/sdm/libs/core/Android.mk
new file mode 100644
index 0000000..c5002a9
--- /dev/null
+++ b/sdm845/sdm/libs/core/Android.mk
@@ -0,0 +1,85 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/../../../common.mk
+
+LOCAL_MODULE                  := libsdmcore
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_HEADER_LIBRARIES        := display_headers
+LOCAL_CFLAGS                  := -fno-operator-names -Wno-unused-parameter -DLOG_TAG=\"SDM\" \
+                                 $(common_flags)
+LOCAL_HW_INTF_PATH_1          := fb
+LOCAL_SHARED_LIBRARIES        := libdl libsdmutils
+
+ifneq ($(TARGET_IS_HEADLESS), true)
+    LOCAL_CFLAGS              += -DCOMPILE_DRM -isystem external/libdrm
+    LOCAL_SHARED_LIBRARIES    += libdrm libdrmutils
+    LOCAL_HW_INTF_PATH_2      := drm
+endif
+
+ifeq ($(TARGET_USES_DRM_PP),true)
+    LOCAL_CFLAGS              += -DPP_DRM_ENABLE
+endif
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
+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 \
+                                 color_manager.cpp \
+                                 hw_events_interface.cpp \
+                                 hw_info_interface.cpp \
+                                 hw_interface.cpp \
+                                 $(LOCAL_HW_INTF_PATH_1)/hw_info.cpp \
+                                 $(LOCAL_HW_INTF_PATH_1)/hw_device.cpp \
+                                 $(LOCAL_HW_INTF_PATH_1)/hw_primary.cpp \
+                                 $(LOCAL_HW_INTF_PATH_1)/hw_hdmi.cpp \
+                                 $(LOCAL_HW_INTF_PATH_1)/hw_virtual.cpp \
+                                 $(LOCAL_HW_INTF_PATH_1)/hw_color_manager.cpp \
+                                 $(LOCAL_HW_INTF_PATH_1)/hw_scale.cpp \
+                                 $(LOCAL_HW_INTF_PATH_1)/hw_events.cpp
+
+ifneq ($(TARGET_IS_HEADLESS), true)
+    LOCAL_SRC_FILES           += $(LOCAL_HW_INTF_PATH_2)/hw_info_drm.cpp \
+                                 $(LOCAL_HW_INTF_PATH_2)/hw_device_drm.cpp \
+                                 $(LOCAL_HW_INTF_PATH_2)/hw_events_drm.cpp \
+                                 $(LOCAL_HW_INTF_PATH_2)/hw_scale_drm.cpp \
+                                 $(LOCAL_HW_INTF_PATH_2)/hw_virtual_drm.cpp \
+                                 $(LOCAL_HW_INTF_PATH_2)/hw_color_manager_drm.cpp
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+
+SDM_HEADER_PATH := ../../include
+include $(CLEAR_VARS)
+LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)/sdm/core
+LOCAL_COPY_HEADERS             = $(SDM_HEADER_PATH)/core/buffer_allocator.h \
+                                 $(SDM_HEADER_PATH)/core/buffer_sync_handler.h \
+                                 $(SDM_HEADER_PATH)/core/core_interface.h \
+                                 $(SDM_HEADER_PATH)/core/debug_interface.h \
+                                 $(SDM_HEADER_PATH)/core/display_interface.h \
+                                 $(SDM_HEADER_PATH)/core/dump_interface.h \
+                                 $(SDM_HEADER_PATH)/core/layer_buffer.h \
+                                 $(SDM_HEADER_PATH)/core/layer_stack.h \
+                                 $(SDM_HEADER_PATH)/core/sdm_types.h \
+                                 $(SDM_HEADER_PATH)/core/socket_handler.h
+include $(BUILD_COPY_HEADERS)
+
+include $(CLEAR_VARS)
+LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)/sdm/private
+LOCAL_COPY_HEADERS             = $(SDM_HEADER_PATH)/private/color_interface.h \
+                                 $(SDM_HEADER_PATH)/private/color_params.h \
+                                 $(SDM_HEADER_PATH)/private/extension_interface.h \
+                                 $(SDM_HEADER_PATH)/private/hw_info_types.h \
+                                 $(SDM_HEADER_PATH)/private/partial_update_interface.h \
+                                 $(SDM_HEADER_PATH)/private/resource_interface.h \
+                                 $(SDM_HEADER_PATH)/private/strategy_interface.h \
+                                 $(SDM_HEADER_PATH)/private/dpps_control_interface.h
+include $(BUILD_COPY_HEADERS)
diff --git a/sdm845/sdm/libs/core/Makefile.am b/sdm845/sdm/libs/core/Makefile.am
new file mode 100644
index 0000000..2b45d8e
--- /dev/null
+++ b/sdm845/sdm/libs/core/Makefile.am
@@ -0,0 +1,47 @@
+HEADER_PATH := ${WORKSPACE}/display/display-hal/sdm/include
+
+c_sources = core_interface.cpp \
+            core_impl.cpp \
+            display_base.cpp \
+            display_primary.cpp \
+            display_hdmi.cpp \
+            display_virtual.cpp \
+            comp_manager.cpp \
+            strategy.cpp \
+            resource_default.cpp \
+            dump_impl.cpp \
+            color_manager.cpp \
+            hw_interface.cpp \
+            hw_info_interface.cpp \
+            hw_events_interface.cpp \
+            fb/hw_info.cpp \
+            fb/hw_device.cpp \
+            fb/hw_primary.cpp \
+            fb/hw_hdmi.cpp \
+            fb/hw_virtual.cpp \
+            fb/hw_color_manager.cpp \
+            fb/hw_scale.cpp \
+            fb/hw_events.cpp
+
+core_h_sources = $(HEADER_PATH)/core/*.h
+
+core_includedir = $(includedir)/sdm/core
+core_include_HEADERS = $(core_h_sources)
+
+private_h_sources = $(HEADER_PATH)/private/*.h
+
+private_includedir = $(includedir)/sdm/private
+private_include_HEADERS = $(private_h_sources)
+
+utils_h_sources = $(HEADER_PATH)/utils/*.h
+
+utils_includedir = $(includedir)/sdm/utils
+utils_include_HEADERS = $(utils_h_sources)
+
+lib_LTLIBRARIES = libsdmcore.la
+libsdmcore_la_CC = @CC@
+libsdmcore_la_SOURCES = $(c_sources)
+libsdmcore_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"SDM\"
+libsdmcore_la_CPPFLAGS = $(AM_CPPFLAGS)
+libsdmcore_la_LIBADD = ../utils/libsdmutils.la
+libsdmcore_la_LDFLAGS = -shared -avoid-version
diff --git a/sdm845/sdm/libs/core/color_manager.cpp b/sdm845/sdm/libs/core/color_manager.cpp
new file mode 100644
index 0000000..938ab99
--- /dev/null
+++ b/sdm845/sdm/libs/core/color_manager.cpp
@@ -0,0 +1,243 @@
+/* Copyright (c) 2015 - 2017, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* 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 <private/color_interface.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include "color_manager.h"
+
+#define __CLASS__ "ColorManager"
+
+namespace sdm {
+
+DynLib ColorManagerProxy::color_lib_;
+CreateColorInterface ColorManagerProxy::create_intf_ = NULL;
+DestroyColorInterface ColorManagerProxy::destroy_intf_ = NULL;
+HWResourceInfo ColorManagerProxy::hw_res_info_;
+
+// Below two functions are part of concrete implementation for SDM core private
+// color_params.h
+void PPFeaturesConfig::Reset() {
+  for (int i = 0; i < kMaxNumPPFeatures; i++) {
+    if (feature_[i]) {
+      delete feature_[i];
+      feature_[i] = NULL;
+    }
+  }
+  dirty_ = false;
+  next_idx_ = 0;
+}
+
+DisplayError PPFeaturesConfig::RetrieveNextFeature(PPFeatureInfo **feature) {
+  DisplayError ret = kErrorNone;
+  uint32_t i(0);
+
+  for (i = next_idx_; i < kMaxNumPPFeatures; i++) {
+    if (feature_[i]) {
+      *feature = feature_[i];
+      next_idx_ = i + 1;
+      break;
+    }
+  }
+
+  if (i == kMaxNumPPFeatures) {
+    ret = kErrorParameters;
+    next_idx_ = 0;
+  }
+
+  return ret;
+}
+
+DisplayError ColorManagerProxy::Init(const HWResourceInfo &hw_res_info) {
+  DisplayError error = kErrorNone;
+
+  // Load color service library and retrieve its entry points.
+  if (color_lib_.Open(COLORMGR_LIBRARY_NAME)) {
+    if (!color_lib_.Sym(CREATE_COLOR_INTERFACE_NAME, reinterpret_cast<void **>(&create_intf_)) ||
+        !color_lib_.Sym(DESTROY_COLOR_INTERFACE_NAME, reinterpret_cast<void **>(&destroy_intf_))) {
+      DLOGW("Fail to retrieve = %s from %s", CREATE_COLOR_INTERFACE_NAME, COLORMGR_LIBRARY_NAME);
+      error = kErrorResources;
+    }
+  } else {
+    DLOGW("Fail to load = %s", COLORMGR_LIBRARY_NAME);
+    error = kErrorResources;
+  }
+
+  hw_res_info_ = hw_res_info;
+
+  return error;
+}
+
+void ColorManagerProxy::Deinit() {
+  color_lib_.~DynLib();
+}
+
+ColorManagerProxy::ColorManagerProxy(DisplayType type, HWInterface *intf,
+                                     const HWDisplayAttributes &attr,
+                                     const HWPanelInfo &info)
+    : device_type_(type), pp_hw_attributes_(), hw_intf_(intf), color_intf_(NULL), pp_features_() {}
+
+ColorManagerProxy *ColorManagerProxy::CreateColorManagerProxy(DisplayType type,
+                                                              HWInterface *hw_intf,
+                                                              const HWDisplayAttributes &attribute,
+                                                              const HWPanelInfo &panel_info) {
+  DisplayError error = kErrorNone;
+  PPFeatureVersion versions;
+
+  // check if all resources are available before invoking factory method from libsdm-color.so.
+  if (!color_lib_ || !create_intf_ || !destroy_intf_) {
+    DLOGW("Information for %s isn't available!", COLORMGR_LIBRARY_NAME);
+    return NULL;
+  }
+
+  ColorManagerProxy *color_manager_proxy =
+      new ColorManagerProxy(type, hw_intf, attribute, panel_info);
+  if (color_manager_proxy) {
+    // 1. need query post-processing feature version from HWInterface.
+    error = color_manager_proxy->hw_intf_->GetPPFeaturesVersion(&versions);
+    PPHWAttributes &hw_attr = color_manager_proxy->pp_hw_attributes_;
+    if (error != kErrorNone) {
+      DLOGW("Fail to get DSPP feature versions");
+    } else {
+      hw_attr.Set(hw_res_info_, panel_info, attribute, versions);
+      DLOGW("PAV2 version is versions = %d, version = %d ",
+            hw_attr.version.version[kGlobalColorFeaturePaV2],
+            versions.version[kGlobalColorFeaturePaV2]);
+    }
+
+    // 2. instantiate concrete ColorInterface from libsdm-color.so, pass all hardware info in.
+    error = create_intf_(COLOR_VERSION_TAG, color_manager_proxy->device_type_, hw_attr,
+                         &color_manager_proxy->color_intf_);
+    if (error != kErrorNone) {
+      DLOGW("Unable to instantiate concrete ColorInterface from %s", COLORMGR_LIBRARY_NAME);
+      delete color_manager_proxy;
+      color_manager_proxy = NULL;
+    }
+  }
+
+  return color_manager_proxy;
+}
+
+ColorManagerProxy::~ColorManagerProxy() {
+  if (destroy_intf_)
+    destroy_intf_(device_type_);
+  color_intf_ = NULL;
+}
+
+DisplayError ColorManagerProxy::ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+                                                     PPDisplayAPIPayload *out_payload,
+                                                     PPPendingParams *pending_action) {
+  DisplayError ret = kErrorNone;
+
+  // On completion, dspp_features_ will be populated and mark dirty with all resolved dspp
+  // feature list with paramaters being transformed into target requirement.
+  ret = color_intf_->ColorSVCRequestRoute(in_payload, out_payload, &pp_features_, pending_action);
+
+  return ret;
+}
+
+DisplayError ColorManagerProxy::ApplyDefaultDisplayMode(void) {
+  DisplayError ret = kErrorNone;
+
+  // On POR, will be invoked from prepare<> request once bootanimation is done.
+  ret = color_intf_->ApplyDefaultDisplayMode(&pp_features_);
+
+  return ret;
+}
+
+bool ColorManagerProxy::NeedsPartialUpdateDisable() {
+  Locker &locker(pp_features_.GetLocker());
+  SCOPE_LOCK(locker);
+
+  return pp_features_.IsDirty();
+}
+
+DisplayError ColorManagerProxy::Commit() {
+  Locker &locker(pp_features_.GetLocker());
+  SCOPE_LOCK(locker);
+
+  DisplayError ret = kErrorNone;
+  if (pp_features_.IsDirty()) {
+    ret = hw_intf_->SetPPFeatures(&pp_features_);
+  }
+
+  return ret;
+}
+
+void PPHWAttributes::Set(const HWResourceInfo &hw_res,
+                         const HWPanelInfo &panel_info,
+                         const DisplayConfigVariableInfo &attr,
+                         const PPFeatureVersion &feature_ver) {
+  HWResourceInfo &res = *this;
+  res = hw_res;
+  HWPanelInfo &panel = *this;
+  panel = panel_info;
+  DisplayConfigVariableInfo &attributes = *this;
+  attributes = attr;
+  version = feature_ver;
+  panel_max_brightness = panel_info.panel_max_brightness;
+
+  if (strlen(panel_info.panel_name)) {
+    snprintf(&panel_name[0], sizeof(panel_name), "%s", &panel_info.panel_name[0]);
+    char *tmp = panel_name;
+    while ((tmp = strstr(tmp, " ")) != NULL)
+      *tmp = '_';
+    if ((tmp = strstr(panel_name, "\n")) != NULL)
+      *tmp = '\0';
+  }
+}
+
+DisplayError ColorManagerProxy::ColorMgrGetNumOfModes(uint32_t *mode_cnt) {
+  return color_intf_->ColorIntfGetNumDisplayModes(&pp_features_, 0, mode_cnt);
+}
+
+DisplayError ColorManagerProxy::ColorMgrGetModes(uint32_t *mode_cnt,
+                                                 SDEDisplayMode *modes) {
+  return color_intf_->ColorIntfEnumerateDisplayModes(&pp_features_, 0, modes, mode_cnt);
+}
+
+DisplayError ColorManagerProxy::ColorMgrSetMode(int32_t color_mode_id) {
+  return color_intf_->ColorIntfSetDisplayMode(&pp_features_, 0, color_mode_id);
+}
+
+DisplayError ColorManagerProxy::ColorMgrGetModeInfo(int32_t mode_id, AttrVal *query) {
+  return color_intf_->ColorIntfGetModeInfo(&pp_features_, 0, mode_id, query);
+}
+
+DisplayError ColorManagerProxy::ColorMgrSetColorTransform(uint32_t length,
+                                                          const double *trans_data) {
+  return color_intf_->ColorIntfSetColorTransform(&pp_features_, 0, length, trans_data);
+}
+
+DisplayError ColorManagerProxy::ColorMgrGetDefaultModeID(int32_t *mode_id) {
+  return color_intf_->ColorIntfGetDefaultModeID(&pp_features_, 0, mode_id);
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/color_manager.h b/sdm845/sdm/libs/core/color_manager.h
new file mode 100644
index 0000000..db050af
--- /dev/null
+++ b/sdm845/sdm/libs/core/color_manager.h
@@ -0,0 +1,98 @@
+/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef __COLOR_MANAGER_H__
+#define __COLOR_MANAGER_H__
+
+#include <stdlib.h>
+#include <core/sdm_types.h>
+#include <utils/locker.h>
+#include <private/color_interface.h>
+#include <utils/sys.h>
+#include <utils/debug.h>
+#include "hw_interface.h"
+
+namespace sdm {
+
+/*
+ * ColorManager proxy to maintain necessary information to interact with underlying color service.
+ * Each display object has its own proxy.
+ */
+class ColorManagerProxy {
+ public:
+  static DisplayError Init(const HWResourceInfo &hw_res_info);
+  static void Deinit();
+
+  /* Create ColorManagerProxy for this display object, following things need to be happening
+   * 1. Instantiates concrete ColorInerface implementation.
+   * 2. Pass all display object specific informations into it.
+   * 3. Populate necessary resources.
+   * 4. Need get panel name for hw_panel_info_.
+   */
+  static ColorManagerProxy *CreateColorManagerProxy(DisplayType type, HWInterface *hw_intf,
+                                                    const HWDisplayAttributes &attribute,
+                                                    const HWPanelInfo &panel_info);
+
+  /* need reverse the effect of CreateColorManagerProxy. */
+  ~ColorManagerProxy();
+
+  DisplayError ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+                                    PPDisplayAPIPayload *out_payload,
+                                    PPPendingParams *pending_action);
+  DisplayError ApplyDefaultDisplayMode();
+  DisplayError ColorMgrGetNumOfModes(uint32_t *mode_cnt);
+  DisplayError ColorMgrGetModes(uint32_t *mode_cnt, SDEDisplayMode *modes);
+  DisplayError ColorMgrSetMode(int32_t color_mode_id);
+  DisplayError ColorMgrGetModeInfo(int32_t mode_id, AttrVal *query);
+  DisplayError ColorMgrSetColorTransform(uint32_t length, const double *trans_data);
+  DisplayError ColorMgrGetDefaultModeID(int32_t *mode_id);
+  bool NeedsPartialUpdateDisable();
+  DisplayError Commit();
+
+ protected:
+  ColorManagerProxy() {}
+  ColorManagerProxy(DisplayType type, HWInterface *intf, const HWDisplayAttributes &attr,
+                    const HWPanelInfo &info);
+
+ private:
+  static DynLib color_lib_;
+  static CreateColorInterface create_intf_;
+  static DestroyColorInterface destroy_intf_;
+  static HWResourceInfo hw_res_info_;
+
+  DisplayType device_type_;
+  PPHWAttributes pp_hw_attributes_;
+  HWInterface *hw_intf_;
+  ColorInterface *color_intf_;
+  PPFeaturesConfig pp_features_;
+};
+
+}  // namespace sdm
+
+#endif  // __COLOR_MANAGER_H__
diff --git a/sdm845/sdm/libs/core/comp_manager.cpp b/sdm845/sdm/libs/core/comp_manager.cpp
new file mode 100644
index 0000000..d18b5b8
--- /dev/null
+++ b/sdm845/sdm/libs/core/comp_manager.cpp
@@ -0,0 +1,536 @@
+/*
+* Copyright (c) 2014 - 2017, 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 {
+
+DisplayError CompManager::Init(const HWResourceInfo &hw_res_info,
+                               ExtensionInterface *extension_intf,
+                               BufferAllocator *buffer_allocator,
+                               BufferSyncHandler *buffer_sync_handler,
+                               SocketHandler *socket_handler) {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
+
+  if (extension_intf) {
+    error = extension_intf->CreateResourceExtn(hw_res_info, buffer_allocator, buffer_sync_handler,
+                                               &resource_intf_);
+    extension_intf->CreateDppsControlExtn(&dpps_ctrl_intf_, socket_handler);
+  } else {
+    error = ResourceDefault::CreateResourceDefault(hw_res_info, &resource_intf_);
+  }
+
+  if (error != kErrorNone) {
+    if (extension_intf) {
+      extension_intf->DestroyDppsControlExtn(dpps_ctrl_intf_);
+    }
+    return error;
+  }
+
+  hw_res_info_ = hw_res_info;
+  buffer_allocator_ = buffer_allocator;
+  extension_intf_ = extension_intf;
+
+  return error;
+}
+
+DisplayError CompManager::Deinit() {
+  SCOPE_LOCK(locker_);
+
+  if (extension_intf_) {
+    extension_intf_->DestroyResourceExtn(resource_intf_);
+    extension_intf_->DestroyDppsControlExtn(dpps_ctrl_intf_);
+  } else {
+    ResourceDefault::DestroyResourceDefault(resource_intf_);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError CompManager::RegisterDisplay(DisplayType type,
+                                          const HWDisplayAttributes &display_attributes,
+                                          const HWPanelInfo &hw_panel_info,
+                                          const HWMixerAttributes &mixer_attributes,
+                                          const DisplayConfigVariableInfo &fb_config,
+                                          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_, buffer_allocator_, type, hw_res_info_, hw_panel_info,
+                          mixer_attributes, display_attributes, fb_config);
+  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, display_attributes, hw_panel_info, mixer_attributes,
+                                          &display_comp_ctx->display_resource_ctx);
+  if (error != kErrorNone) {
+    strategy->Deinit();
+    delete strategy;
+    delete display_comp_ctx;
+    display_comp_ctx = NULL;
+    return error;
+  }
+
+  registered_displays_[type] = 1;
+  display_comp_ctx->is_primary_panel = hw_panel_info.is_primary_panel;
+  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 (!display_comp_ctx->is_primary_panel) {
+    safe_mode_ = true;
+    max_sde_ext_layers_ = UINT32(Debug::GetExtMaxlayers());
+  }
+
+  DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+           "display type %d", registered_displays_.to_ulong(), configured_displays_.to_ulong(),
+           display_comp_ctx->display_type);
+
+  return kErrorNone;
+}
+
+DisplayError CompManager::UnregisterDisplay(Handle display_ctx) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  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;
+
+  registered_displays_[display_comp_ctx->display_type] = 0;
+  configured_displays_[display_comp_ctx->display_type] = 0;
+
+  if (display_comp_ctx->display_type == kHDMI) {
+    max_layers_ = kMaxSDELayers;
+  }
+
+  DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+           "display type %d", registered_displays_.to_ulong(), configured_displays_.to_ulong(),
+           display_comp_ctx->display_type);
+
+  delete display_comp_ctx;
+  display_comp_ctx = NULL;
+  return kErrorNone;
+}
+
+DisplayError CompManager::ReconfigureDisplay(Handle comp_handle,
+                                             const HWDisplayAttributes &display_attributes,
+                                             const HWPanelInfo &hw_panel_info,
+                                             const HWMixerAttributes &mixer_attributes,
+                                             const DisplayConfigVariableInfo &fb_config) {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(comp_handle);
+
+  error = resource_intf_->ReconfigureDisplay(display_comp_ctx->display_resource_ctx,
+                                             display_attributes, hw_panel_info, mixer_attributes);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  if (display_comp_ctx->strategy) {
+    error = display_comp_ctx->strategy->Reconfigure(hw_panel_info, display_attributes,
+                                                    mixer_attributes, fb_config);
+    if (error != kErrorNone) {
+      DLOGE("Unable to Reconfigure strategy.");
+      display_comp_ctx->strategy->Deinit();
+      delete display_comp_ctx->strategy;
+      display_comp_ctx->strategy = NULL;
+      return error;
+    }
+  }
+
+  // For HDMI S3D mode, set max_layers_ to 0 so that primary display would fall back
+  // to GPU composition to release pipes for HDMI.
+  if (display_comp_ctx->display_type == kHDMI) {
+    if (hw_panel_info.s3d_mode != kS3DModeNone) {
+      max_layers_ = 0;
+    } else {
+      max_layers_ = kMaxSDELayers;
+    }
+  }
+
+  return error;
+}
+
+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_;
+  constraints->max_layers = max_layers_;
+
+  // Limit 2 layer SDE Comp if its not a Primary Display.
+  // Safe mode is the policy for External display on a low end device.
+  if (!display_comp_ctx->is_primary_panel) {
+    bool low_end_hw = ((hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe +
+                        hw_res_info_.num_dma_pipe) <= kSafeModeThreshold);
+    constraints->max_layers = max_sde_ext_layers_;
+    constraints->safe_mode = (low_end_hw && !hw_res_info_.separate_rotator) ? true : safe_mode_;
+  }
+
+  // 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;
+  }
+
+  // TODO(user): App layer count will change for hybrid composition
+  uint32_t app_layer_count = UINT32(hw_layers->info.stack->layers.size()) - 1;
+  if (display_comp_ctx->idle_fallback || display_comp_ctx->thermal_fallback_) {
+    // Handle the idle timeout by falling back
+    constraints->safe_mode = true;
+  }
+
+  // Avoid safe mode, if there is only one app layer.
+  if (app_layer_count == 1) {
+     constraints->safe_mode = false;
+  }
+}
+
+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->pu_constraints);
+  display_comp_ctx->remaining_strategies = display_comp_ctx->max_strategies;
+}
+
+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_->Prepare(display_resource_ctx, hw_layers);
+      // Exit if successfully prepared 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::Commit(Handle display_ctx, HWLayers *hw_layers) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  return resource_intf_->Commit(display_comp_ctx->display_resource_ctx, hw_layers);
+}
+
+DisplayError CompManager::ReConfigure(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;
+  resource_intf_->Start(display_resource_ctx);
+  error = resource_intf_->Prepare(display_resource_ctx, hw_layers);
+
+  if (error != kErrorNone) {
+    DLOGE("Reconfigure failed for display = %d", display_comp_ctx->display_type);
+  }
+
+  resource_intf_->Stop(display_resource_ctx);
+  if (error != kErrorNone) {
+      error = resource_intf_->PostPrepare(display_resource_ctx, hw_layers);
+  }
+
+  return error;
+}
+
+DisplayError CompManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+  configured_displays_[display_comp_ctx->display_type] = 1;
+  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);
+
+  display_comp_ctx->strategy->Purge();
+}
+
+DisplayError CompManager::SetIdleTimeoutMs(Handle display_ctx, uint32_t active_ms) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  return display_comp_ctx->strategy->SetIdleTimeoutMs(active_ms);
+}
+
+void CompManager::ProcessIdleTimeout(Handle display_ctx) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  if (!display_comp_ctx) {
+    return;
+  }
+
+  display_comp_ctx->idle_fallback = true;
+}
+
+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->thermal_fallback_ = true;
+  } else {
+    display_comp_ctx->thermal_fallback_ = false;
+  }
+}
+
+void CompManager::ProcessIdlePowerCollapse(Handle display_ctx) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+          reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  if (display_comp_ctx) {
+    resource_intf_->Perform(ResourceInterface::kCmdResetScalarLUT,
+                            display_comp_ctx->display_resource_ctx);
+  }
+}
+
+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::ControlPartialUpdate(Handle display_ctx, bool enable) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+  display_comp_ctx->pu_constraints.enable = enable;
+}
+
+void CompManager::AppendDump(char *buffer, uint32_t length) {
+  SCOPE_LOCK(locker_);
+}
+
+DisplayError CompManager::ValidateScaling(const LayerRect &crop, const LayerRect &dst,
+                                          bool rotate90) {
+  BufferLayout layout = Debug::IsUbwcTiledFrameBuffer() ? kUBWC : kLinear;
+  return resource_intf_->ValidateScaling(crop, dst, rotate90, layout, true);
+}
+
+DisplayError CompManager::ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers,
+                                                 int x, int y) {
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+  Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
+
+  return resource_intf_->ValidateCursorPosition(display_resource_ctx, hw_layers, x, y);
+}
+
+DisplayError CompManager::SetMaxBandwidthMode(HWBwModes mode) {
+  if ((hw_res_info_.has_dyn_bw_support == false) || (mode >= kBwModeMax)) {
+    return kErrorNotSupported;
+  }
+
+  return resource_intf_->SetMaxBandwidthMode(mode);
+}
+
+DisplayError CompManager::GetScaleLutConfig(HWScaleLutInfo *lut_info) {
+  return resource_intf_->GetScaleLutConfig(lut_info);
+}
+
+DisplayError CompManager::SetDetailEnhancerData(Handle display_ctx,
+                                                const DisplayDetailEnhancerData &de_data) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  return resource_intf_->SetDetailEnhancerData(display_comp_ctx->display_resource_ctx, de_data);
+}
+
+DisplayError CompManager::SetCompositionState(Handle display_ctx,
+                                              LayerComposition composition_type, bool enable) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  return display_comp_ctx->strategy->SetCompositionState(composition_type, enable);
+}
+
+DisplayError CompManager::ControlDpps(bool enable) {
+  if (dpps_ctrl_intf_) {
+    return enable ? dpps_ctrl_intf_->On() : dpps_ctrl_intf_->Off();
+  }
+
+  return kErrorNone;
+}
+
+bool CompManager::SetDisplayState(Handle display_ctx,
+                                  DisplayState state, DisplayType display_type) {
+  display_state_[display_type] = state;
+
+  switch (state) {
+  case kStateOff:
+    Purge(display_ctx);
+    configured_displays_.reset(display_type);
+    DLOGV_IF(kTagCompManager, "configured_displays_ = 0x%x", configured_displays_);
+    break;
+
+  case kStateOn:
+    if (registered_displays_.count() > 1) {
+      safe_mode_ = true;
+      DLOGV_IF(kTagCompManager, "safe_mode = %d", safe_mode_);
+    }
+    break;
+
+  default:
+    break;
+  }
+
+  return true;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/comp_manager.h b/sdm845/sdm/libs/core/comp_manager.h
new file mode 100644
index 0000000..c6b8972
--- /dev/null
+++ b/sdm845/sdm/libs/core/comp_manager.h
@@ -0,0 +1,121 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <bitset>
+
+#include "strategy.h"
+#include "resource_default.h"
+#include "hw_interface.h"
+#include "dump_impl.h"
+
+namespace sdm {
+
+class CompManager : public DumpImpl {
+ public:
+  DisplayError Init(const HWResourceInfo &hw_res_info_, ExtensionInterface *extension_intf,
+                    BufferAllocator *buffer_allocator, BufferSyncHandler *buffer_sync_handler,
+                    SocketHandler *socket_handler);
+  DisplayError Deinit();
+  DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &display_attributes,
+                               const HWPanelInfo &hw_panel_info,
+                               const HWMixerAttributes &mixer_attributes,
+                               const DisplayConfigVariableInfo &fb_config, Handle *display_ctx);
+  DisplayError UnregisterDisplay(Handle display_ctx);
+  DisplayError ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &display_attributes,
+                                  const HWPanelInfo &hw_panel_info,
+                                  const HWMixerAttributes &mixer_attributes,
+                                  const DisplayConfigVariableInfo &fb_config);
+  void PrePrepare(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError Commit(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError ReConfigure(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
+  void Purge(Handle display_ctx);
+  DisplayError SetIdleTimeoutMs(Handle display_ctx, uint32_t active_ms);
+  void ProcessIdleTimeout(Handle display_ctx);
+  void ProcessThermalEvent(Handle display_ctx, int64_t thermal_level);
+  void ProcessIdlePowerCollapse(Handle display_ctx);
+  DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
+  void ControlPartialUpdate(Handle display_ctx, bool enable);
+  DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+  DisplayError ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers, int x, int y);
+  bool SetDisplayState(Handle display_ctx, DisplayState state, DisplayType display_type);
+  DisplayError SetMaxBandwidthMode(HWBwModes mode);
+  DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info);
+  DisplayError SetDetailEnhancerData(Handle display_ctx, const DisplayDetailEnhancerData &de_data);
+  DisplayError SetCompositionState(Handle display_ctx, LayerComposition composition_type,
+                                   bool enable);
+  DisplayError ControlDpps(bool enable);
+
+  // DumpImpl method
+  virtual void AppendDump(char *buffer, uint32_t length);
+
+ private:
+  static const int kMaxThermalLevel = 3;
+  static const int kSafeModeThreshold = 4;
+
+  void PrepareStrategyConstraints(Handle display_ctx, HWLayers *hw_layers);
+
+  struct DisplayCompositionContext {
+    Strategy *strategy = NULL;
+    StrategyConstraints constraints;
+    Handle display_resource_ctx = NULL;
+    DisplayType display_type = kPrimary;
+    uint32_t max_strategies = 0;
+    uint32_t remaining_strategies = 0;
+    bool idle_fallback = false;
+    bool thermal_fallback_ = false;
+    // Using primary panel flag of hw panel to configure Constraints. We do not need other hw
+    // panel parameters for now.
+    bool is_primary_panel = false;
+    PUConstraints pu_constraints = {};
+  };
+
+  Locker locker_;
+  ResourceInterface *resource_intf_ = NULL;
+  std::bitset<kDisplayMax> registered_displays_;  // Bit mask of registered displays
+  std::bitset<kDisplayMax> configured_displays_;  // Bit mask of sucessfully configured displays
+  uint32_t display_state_[kDisplayMax] = {};
+  bool safe_mode_ = false;              // 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_;
+  BufferAllocator *buffer_allocator_ = NULL;
+  ExtensionInterface *extension_intf_ = NULL;
+  uint32_t max_layers_ = kMaxSDELayers;
+  uint32_t max_sde_ext_layers_ = 0;
+  DppsControlInterface *dpps_ctrl_intf_ = NULL;
+};
+
+}  // namespace sdm
+
+#endif  // __COMP_MANAGER_H__
+
diff --git a/sdm845/sdm/libs/core/core_impl.cpp b/sdm845/sdm/libs/core/core_impl.cpp
new file mode 100644
index 0000000..661616e
--- /dev/null
+++ b/sdm845/sdm/libs/core/core_impl.cpp
@@ -0,0 +1,182 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#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"
+#include "color_manager.h"
+
+#define __CLASS__ "CoreImpl"
+
+namespace sdm {
+
+CoreImpl::CoreImpl(BufferAllocator *buffer_allocator,
+                   BufferSyncHandler *buffer_sync_handler,
+                   SocketHandler *socket_handler)
+  : buffer_allocator_(buffer_allocator), buffer_sync_handler_(buffer_sync_handler),
+    socket_handler_(socket_handler) {
+}
+
+DisplayError CoreImpl::Init() {
+  SCOPE_LOCK(locker_);
+  DisplayError error = kErrorNone;
+
+  // Try to load extension library & get handle to its interface.
+  if (extension_lib_.Open(EXTENSION_LIBRARY_NAME)) {
+    if (!extension_lib_.Sym(CREATE_EXTENSION_INTERFACE_NAME,
+                            reinterpret_cast<void **>(&create_extension_intf_)) ||
+        !extension_lib_.Sym(DESTROY_EXTENSION_INTERFACE_NAME,
+                            reinterpret_cast<void **>(&destroy_extension_intf_))) {
+      DLOGE("Unable to load symbols, error = %s", extension_lib_.Error());
+      return kErrorUndefined;
+    }
+
+    error = create_extension_intf_(EXTENSION_VERSION_TAG, &extension_intf_);
+    if (error != kErrorNone) {
+      DLOGE("Unable to create interface");
+      return error;
+    }
+  } else {
+    DLOGW("Unable to load = %s, error = %s", EXTENSION_LIBRARY_NAME, extension_lib_.Error());
+  }
+
+  error = HWInfoInterface::Create(&hw_info_intf_);
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  error = hw_info_intf_->GetHWResourceInfo(&hw_resource_);
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  error = comp_mgr_.Init(hw_resource_, extension_intf_, buffer_allocator_,
+                         buffer_sync_handler_, socket_handler_);
+
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  error = ColorManagerProxy::Init(hw_resource_);
+  // if failed, doesn't affect display core functionalities.
+  if (error != kErrorNone) {
+    DLOGW("Unable creating color manager and continue without it.");
+  }
+
+  return kErrorNone;
+
+CleanupOnError:
+  if (hw_info_intf_) {
+    HWInfoInterface::Destroy(hw_info_intf_);
+  }
+
+  return error;
+}
+
+DisplayError CoreImpl::Deinit() {
+  SCOPE_LOCK(locker_);
+
+  ColorManagerProxy::Deinit();
+
+  comp_mgr_.Deinit();
+  HWInfoInterface::Destroy(hw_info_intf_);
+
+  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_,
+                                      buffer_allocator_, &comp_mgr_);
+    break;
+  case kHDMI:
+    display_base = new DisplayHDMI(event_handler, hw_info_intf_, buffer_sync_handler_,
+                                   buffer_allocator_, &comp_mgr_);
+    break;
+  case kVirtual:
+    display_base = new DisplayVirtual(event_handler, hw_info_intf_, buffer_sync_handler_,
+                                      buffer_allocator_, &comp_mgr_);
+    break;
+  default:
+    DLOGE("Spurious display type %d", type);
+    return kErrorParameters;
+  }
+
+  if (!display_base) {
+    return kErrorMemory;
+  }
+
+  DisplayError error = display_base->Init();
+  if (error != kErrorNone) {
+    delete display_base;
+    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;
+
+  return kErrorNone;
+}
+
+DisplayError CoreImpl::SetMaxBandwidthMode(HWBwModes mode) {
+  SCOPE_LOCK(locker_);
+
+  return comp_mgr_.SetMaxBandwidthMode(mode);
+}
+
+DisplayError CoreImpl::GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) {
+  return hw_info_intf_->GetFirstDisplayInterfaceType(hw_disp_info);
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/core/core_impl.h b/sdm845/sdm/libs/core/core_impl.h
new file mode 100644
index 0000000..2647c78
--- /dev/null
+++ b/sdm845/sdm/libs/core/core_impl.h
@@ -0,0 +1,79 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __CORE_IMPL_H__
+#define __CORE_IMPL_H__
+
+#include <core/core_interface.h>
+#include <private/extension_interface.h>
+#include <private/color_interface.h>
+#include <utils/locker.h>
+#include <utils/sys.h>
+
+#include "hw_interface.h"
+#include "comp_manager.h"
+
+#define SET_REVISION(major, minor) ((major << 8) | minor)
+
+namespace sdm {
+
+class CoreImpl : public CoreInterface {
+ public:
+  // This class implements display core interface revision 1.0.
+  static const uint16_t kRevision = SET_REVISION(1, 0);
+  CoreImpl(BufferAllocator *buffer_allocator, BufferSyncHandler *buffer_sync_handler,
+           SocketHandler *socket_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);
+  virtual DisplayError SetMaxBandwidthMode(HWBwModes mode);
+  virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info);
+
+ protected:
+  Locker locker_;
+  BufferAllocator *buffer_allocator_ = NULL;
+  BufferSyncHandler *buffer_sync_handler_ = NULL;
+  HWResourceInfo hw_resource_;
+  CompManager comp_mgr_;
+  HWInfoInterface *hw_info_intf_ = NULL;
+  DynLib extension_lib_;
+  ExtensionInterface *extension_intf_ = NULL;
+  CreateExtensionInterface create_extension_intf_ = NULL;
+  DestroyExtensionInterface destroy_extension_intf_ = NULL;
+  SocketHandler *socket_handler_ = NULL;
+};
+
+}  // namespace sdm
+
+#endif  // __CORE_IMPL_H__
+
diff --git a/sdm845/sdm/libs/core/core_interface.cpp b/sdm845/sdm/libs/core/core_interface.cpp
new file mode 100644
index 0000000..911ad01
--- /dev/null
+++ b/sdm845/sdm/libs/core/core_interface.cpp
@@ -0,0 +1,133 @@
+/*
+* 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(DebugHandler *debug_handler,
+                                       BufferAllocator *buffer_allocator,
+                                       BufferSyncHandler *buffer_sync_handler,
+                                       CoreInterface **interface, uint32_t client_version) {
+  return CreateCore(debug_handler, buffer_allocator, buffer_sync_handler, NULL,
+                    interface, client_version);
+}
+
+DisplayError CoreInterface::CreateCore(DebugHandler *debug_handler,
+                                       BufferAllocator *buffer_allocator,
+                                       BufferSyncHandler *buffer_sync_handler,
+                                       SocketHandler *socket_handler,
+                                       CoreInterface **interface, uint32_t client_version) {
+  SCOPE_LOCK(g_core.locker);
+
+  if (!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(buffer_allocator, buffer_sync_handler, socket_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/sdm845/sdm/libs/core/display_base.cpp b/sdm845/sdm/libs/core/display_base.cpp
new file mode 100644
index 0000000..618dd2e
--- /dev/null
+++ b/sdm845/sdm/libs/core/display_base.cpp
@@ -0,0 +1,1445 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <utils/formats.h>
+#include <utils/rect.h>
+#include <string>
+#include <vector>
+#include <algorithm>
+
+#include "display_base.h"
+#include "hw_info_interface.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,
+                         BufferAllocator *buffer_allocator, CompManager *comp_manager,
+                         HWInfoInterface *hw_info_intf)
+  : display_type_(display_type), event_handler_(event_handler), hw_device_type_(hw_device_type),
+    buffer_sync_handler_(buffer_sync_handler), buffer_allocator_(buffer_allocator),
+    comp_manager_(comp_manager), hw_info_intf_(hw_info_intf) {
+}
+
+DisplayError DisplayBase::Init() {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+  hw_panel_info_ = HWPanelInfo();
+  hw_intf_->GetHWPanelInfo(&hw_panel_info_);
+
+  uint32_t active_index = 0;
+  hw_intf_->GetActiveConfig(&active_index);
+  hw_intf_->GetDisplayAttributes(active_index, &display_attributes_);
+  fb_config_ = display_attributes_;
+
+  error = Debug::GetMixerResolution(&mixer_attributes_.width, &mixer_attributes_.height);
+  if (error == kErrorNone) {
+    hw_intf_->SetMixerAttributes(mixer_attributes_);
+  }
+
+  error = hw_intf_->GetMixerAttributes(&mixer_attributes_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  // Override x_pixels and y_pixels of frame buffer with mixer width and height
+  fb_config_.x_pixels = mixer_attributes_.width;
+  fb_config_.y_pixels = mixer_attributes_.height;
+
+  HWScaleLutInfo lut_info = {};
+  error = comp_manager_->GetScaleLutConfig(&lut_info);
+  if (error == kErrorNone) {
+    error = hw_intf_->SetScaleLutConfig(&lut_info);
+    if (error != kErrorNone) {
+      goto CleanupOnError;
+    }
+  }
+
+  error = comp_manager_->RegisterDisplay(display_type_, display_attributes_, hw_panel_info_,
+                                         mixer_attributes_, fb_config_, &display_comp_ctx_);
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  if (hw_info_intf_) {
+    HWResourceInfo hw_resource_info = HWResourceInfo();
+    hw_info_intf_->GetHWResourceInfo(&hw_resource_info);
+    auto max_mixer_stages = hw_resource_info.num_blending_stages;
+    int property_value = Debug::GetMaxPipesPerMixer(display_type_);
+    if (property_value >= 0) {
+      max_mixer_stages = std::min(UINT32(property_value), hw_resource_info.num_blending_stages);
+    }
+    DisplayBase::SetMaxMixerStages(max_mixer_stages);
+  }
+
+  color_mgr_ = ColorManagerProxy::CreateColorManagerProxy(display_type_, hw_intf_,
+                               display_attributes_, hw_panel_info_);
+  if (!color_mgr_) {
+    DLOGW("Unable to create ColorManagerProxy for display = %d", display_type_);
+  } else if (InitializeColorModes() != kErrorNone) {
+    DLOGW("InitColorModes failed for display = %d", display_type_);
+  }
+
+  Debug::Get()->GetProperty("sdm.disable_hdr_lut_gen", &disable_hdr_lut_gen_);
+
+  return kErrorNone;
+
+CleanupOnError:
+  if (display_comp_ctx_) {
+    comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  }
+
+  return error;
+}
+
+DisplayError DisplayBase::Deinit() {
+  {  // Scope for lock
+    lock_guard<recursive_mutex> obj(recursive_mutex_);
+    color_modes_.clear();
+    color_mode_map_.clear();
+    color_mode_attr_map_.clear();
+
+    if (color_mgr_) {
+      delete color_mgr_;
+      color_mgr_ = NULL;
+    }
+
+    comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  }
+  HWEventsInterface::Destroy(hw_events_intf_);
+  HWInterface::Destroy(hw_intf_);
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::BuildLayerStackStats(LayerStack *layer_stack) {
+  std::vector<Layer *> &layers = layer_stack->layers;
+  HWLayersInfo &hw_layers_info = hw_layers_.info;
+
+  hw_layers_info.stack = layer_stack;
+
+  for (auto &layer : layers) {
+    if (layer->composition == kCompositionGPUTarget) {
+      hw_layers_info.gpu_target_index = hw_layers_info.app_layer_count;
+      break;
+    }
+    hw_layers_info.app_layer_count++;
+  }
+
+  DLOGV_IF(kTagNone, "LayerStack layer_count: %d, app_layer_count: %d, gpu_target_index: %d, "
+           "display type: %d", layers.size(), hw_layers_info.app_layer_count,
+           hw_layers_info.gpu_target_index, display_type_);
+
+  if (!hw_layers_info.app_layer_count) {
+    DLOGW("Layer count is zero");
+    return kErrorNoAppLayers;
+  }
+
+  if (hw_layers_info.gpu_target_index) {
+    return ValidateGPUTargetParams();
+  }
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::ValidateGPUTargetParams() {
+  HWLayersInfo &hw_layers_info = hw_layers_.info;
+  Layer *gpu_target_layer = hw_layers_info.stack->layers.at(hw_layers_info.gpu_target_index);
+
+  if (!IsValid(gpu_target_layer->src_rect)) {
+    DLOGE("Invalid src rect for GPU target layer");
+    return kErrorParameters;
+  }
+
+  if (!IsValid(gpu_target_layer->dst_rect)) {
+    DLOGE("Invalid dst rect for GPU target layer");
+    return kErrorParameters;
+  }
+
+  float layer_mixer_width = FLOAT(mixer_attributes_.width);
+  float layer_mixer_height = FLOAT(mixer_attributes_.height);
+  float fb_width = FLOAT(fb_config_.x_pixels);
+  float fb_height = FLOAT(fb_config_.y_pixels);
+  LayerRect src_domain = (LayerRect){0.0f, 0.0f, fb_width, fb_height};
+  LayerRect dst_domain = (LayerRect){0.0f, 0.0f, layer_mixer_width, layer_mixer_height};
+  LayerRect out_rect = gpu_target_layer->dst_rect;
+
+  MapRect(src_domain, dst_domain, gpu_target_layer->dst_rect, &out_rect);
+  Normalize(1, 1, &out_rect);
+
+  auto gpu_target_layer_dst_xpixels = out_rect.right - out_rect.left;
+  auto gpu_target_layer_dst_ypixels = out_rect.bottom - out_rect.top;
+
+  if (gpu_target_layer_dst_xpixels > mixer_attributes_.width ||
+    gpu_target_layer_dst_ypixels > mixer_attributes_.height) {
+    DLOGE("GPU target layer dst rect is not with in limits gpu wxh %fx%f, mixer wxh %dx%d",
+                  gpu_target_layer_dst_xpixels, gpu_target_layer_dst_ypixels,
+                  mixer_attributes_.width, mixer_attributes_.height);
+    return kErrorParameters;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::Prepare(LayerStack *layer_stack) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+
+  if (!active_) {
+    return kErrorPermission;
+  }
+
+  if (!layer_stack) {
+    return kErrorParameters;
+  }
+
+  error = BuildLayerStackStats(layer_stack);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = HandleHDR(layer_stack);
+  if (error != kErrorNone) {
+    DLOGW("HandleHDR failed");
+    return error;
+  }
+
+  if (color_mgr_ && color_mgr_->NeedsPartialUpdateDisable()) {
+    DisablePartialUpdateOneFrame();
+  }
+
+  if (partial_update_control_ == false || disable_pu_one_frame_) {
+    comp_manager_->ControlPartialUpdate(display_comp_ctx_, false /* enable */);
+    disable_pu_one_frame_ = false;
+  }
+
+  comp_manager_->PrePrepare(display_comp_ctx_, &hw_layers_);
+  while (true) {
+    error = comp_manager_->Prepare(display_comp_ctx_, &hw_layers_);
+    if (error != kErrorNone) {
+      break;
+    }
+
+    error = hw_intf_->Validate(&hw_layers_);
+    if (error == kErrorNone) {
+      // Strategy is successful now, wait for Commit().
+      pending_commit_ = true;
+      break;
+    }
+    if (error == kErrorShutDown) {
+      comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+      return error;
+    }
+  }
+
+  comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+
+  return error;
+}
+
+DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+
+  if (!active_) {
+    pending_commit_ = false;
+    return kErrorPermission;
+  }
+
+  if (!layer_stack) {
+    return kErrorParameters;
+  }
+
+  if (!pending_commit_) {
+    DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
+    return kErrorUndefined;
+  }
+
+  pending_commit_ = false;
+
+  // Layer stack attributes has changed, need to Reconfigure, currently in use for Hybrid Comp
+  if (layer_stack->flags.attributes_changed) {
+    error = comp_manager_->ReConfigure(display_comp_ctx_, &hw_layers_);
+    if (error != kErrorNone) {
+      return error;
+    }
+
+    error = hw_intf_->Validate(&hw_layers_);
+    if (error != kErrorNone) {
+        return error;
+    }
+  }
+
+  CommitLayerParams(layer_stack);
+
+  if (comp_manager_->Commit(display_comp_ctx_, &hw_layers_)) {
+    if (error != kErrorNone) {
+      return error;
+    }
+  }
+
+  // check if feature list cache is dirty and pending.
+  // If dirty, need program to hardware blocks.
+  if (color_mgr_)
+    error = color_mgr_->Commit();
+  if (error != kErrorNone) {  // won't affect this execution path.
+    DLOGW("ColorManager::Commit(...) isn't working");
+  }
+
+  error = hw_intf_->Commit(&hw_layers_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  PostCommitLayerParams(layer_stack);
+
+  if (partial_update_control_) {
+    comp_manager_->ControlPartialUpdate(display_comp_ctx_, true /* enable */);
+  }
+
+  error = comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::Flush() {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+
+  if (!active_) {
+    return kErrorPermission;
+  }
+  hw_layers_.info.hw_layers.clear();
+  error = hw_intf_->Flush();
+  if (error == kErrorNone) {
+    comp_manager_->Purge(display_comp_ctx_);
+    pending_commit_ = false;
+  } else {
+    DLOGW("Unable to flush display = %d", display_type_);
+  }
+
+  return error;
+}
+
+DisplayError DisplayBase::GetDisplayState(DisplayState *state) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (!state) {
+    return kErrorParameters;
+  }
+
+  *state = state_;
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetNumVariableInfoConfigs(uint32_t *count) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  return hw_intf_->GetNumDisplayAttributes(count);
+}
+
+DisplayError DisplayBase::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  HWDisplayAttributes attrib;
+  if (hw_intf_->GetDisplayAttributes(index, &attrib) == kErrorNone) {
+    *variable_info = attrib;
+    return kErrorNone;
+  }
+
+  return kErrorNotSupported;
+}
+
+DisplayError DisplayBase::GetConfig(DisplayConfigFixedInfo *fixed_info) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  fixed_info->is_cmdmode = (hw_panel_info_.mode == kModeCommand);
+
+  HWResourceInfo hw_resource_info = HWResourceInfo();
+  hw_info_intf_->GetHWResourceInfo(&hw_resource_info);
+  // hdr can be supported by display when target and panel supports HDR.
+  fixed_info->hdr_supported = (hw_resource_info.has_hdr && hw_panel_info_.hdr_enabled);
+  // Populate luminance values only if hdr will be supported on that display
+  fixed_info->max_luminance = fixed_info->hdr_supported ? hw_panel_info_.peak_luminance: 0;
+  fixed_info->average_luminance = fixed_info->hdr_supported ? hw_panel_info_.average_luminance : 0;
+  fixed_info->min_luminance = fixed_info->hdr_supported ?  hw_panel_info_.blackness_level: 0;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetActiveConfig(uint32_t *index) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  return hw_intf_->GetActiveConfig(index);
+}
+
+DisplayError DisplayBase::GetVSyncState(bool *enabled) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (!enabled) {
+    return kErrorParameters;
+  }
+
+  *enabled = vsync_enable_;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::SetDisplayState(DisplayState state) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+  bool active = false;
+
+  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.hw_layers.clear();
+    error = hw_intf_->Flush();
+    if (error == kErrorNone) {
+      error = hw_intf_->PowerOff();
+    }
+    break;
+
+  case kStateOn:
+    error = hw_intf_->PowerOn();
+    if (error != kErrorNone) {
+      return error;
+    }
+
+    error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes_,
+                                              hw_panel_info_, mixer_attributes_, fb_config_);
+    if (error != kErrorNone) {
+      return error;
+    }
+
+    active = true;
+    break;
+
+  case kStateDoze:
+    error = hw_intf_->Doze();
+    active = true;
+    break;
+
+  case kStateDozeSuspend:
+    error = hw_intf_->DozeSuspend();
+    if (display_type_ != kPrimary) {
+      active = true;
+    }
+
+    break;
+
+  case kStateStandby:
+    error = hw_intf_->Standby();
+    break;
+
+  default:
+    DLOGE("Spurious state = %d transition requested.", state);
+    break;
+  }
+
+  if (error == kErrorNone) {
+    active_ = active;
+    state_ = state;
+    comp_manager_->SetDisplayState(display_comp_ctx_, state, display_type_);
+  }
+
+  return error;
+}
+
+DisplayError DisplayBase::SetActiveConfig(uint32_t index) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+  uint32_t active_index = 0;
+
+  hw_intf_->GetActiveConfig(&active_index);
+
+  if (active_index == index) {
+    return kErrorNone;
+  }
+
+  error = hw_intf_->SetDisplayAttributes(index);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return ReconfigureDisplay();
+}
+
+DisplayError DisplayBase::SetMaxMixerStages(uint32_t max_mixer_stages) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+
+  error = comp_manager_->SetMaxMixerStages(display_comp_ctx_, max_mixer_stages);
+
+  if (error == kErrorNone) {
+    max_mixer_stages_ = max_mixer_stages;
+  }
+
+  return error;
+}
+
+void DisplayBase::AppendDump(char *buffer, uint32_t length) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  HWDisplayAttributes attrib;
+  uint32_t active_index = 0;
+  uint32_t num_modes = 0;
+  hw_intf_->GetNumDisplayAttributes(&num_modes);
+  hw_intf_->GetActiveConfig(&active_index);
+  hw_intf_->GetDisplayAttributes(active_index, &attrib);
+
+  DumpImpl::AppendString(buffer, length, "\n-----------------------");
+  DumpImpl::AppendString(buffer, length, "\ndevice type: %u", display_type_);
+  DumpImpl::AppendString(buffer, length, "\nstate: %u, vsync on: %u, max. mixer stages: %u",
+                         state_, INT(vsync_enable_), max_mixer_stages_);
+  DumpImpl::AppendString(buffer, length, "\nnum configs: %u, active config index: %u",
+                         num_modes, active_index);
+
+  DisplayConfigVariableInfo &info = attrib;
+
+  uint32_t num_hw_layers = 0;
+  if (hw_layers_.info.stack) {
+    num_hw_layers = UINT32(hw_layers_.info.hw_layers.size());
+  }
+
+  if (num_hw_layers == 0) {
+    DumpImpl::AppendString(buffer, length, "\nNo hardware layers programmed");
+    return;
+  }
+
+  LayerBuffer *out_buffer = hw_layers_.info.stack->output_buffer;
+  if (out_buffer) {
+    DumpImpl::AppendString(buffer, length, "\nres:%u x %u format: %s", out_buffer->width,
+                           out_buffer->height, GetFormatString(out_buffer->format));
+  } else {
+    DumpImpl::AppendString(buffer, length, "\nres:%u x %u, dpi:%.2f x %.2f, fps:%u,"
+                           "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");
+
+  HWLayersInfo &layer_info = hw_layers_.info;
+
+  for (uint32_t i = 0; i < layer_info.left_frame_roi.size(); i++) {
+    LayerRect &l_roi = layer_info.left_frame_roi.at(i);
+    LayerRect &r_roi = layer_info.right_frame_roi.at(i);
+
+    DumpImpl::AppendString(buffer, length, "\nROI%d(L T R B) : LEFT(%d %d %d %d)", i,
+                           INT(l_roi.left), INT(l_roi.top), INT(l_roi.right), INT(l_roi.bottom));
+    if (IsValid(r_roi)) {
+      DumpImpl::AppendString(buffer, length, ", RIGHT(%d %d %d %d)", INT(r_roi.left),
+                             INT(r_roi.top), INT(r_roi.right), INT(r_roi.bottom));
+    }
+  }
+
+  LayerRect &fb_roi = layer_info.partial_fb_roi;
+  if (IsValid(fb_roi)) {
+    DumpImpl::AppendString(buffer, length, "\nPartial FB ROI(L T R B) : (%d %d %d %d)",
+                          INT(fb_roi.left), INT(fb_roi.top), INT(fb_roi.right), INT(fb_roi.bottom));
+  }
+
+  const char *header  = "\n| Idx |  Comp Type  |  Split | WB |  Pipe  |    W x H    |          Format          |  Src Rect (L T R B) |  Dst Rect (L T R B) |  Z |    Flags   | Deci(HxV) | CS | Rng |";  //NOLINT
+  const char *newline = "\n|-----|-------------|--------|----|--------|-------------|--------------------------|---------------------|---------------------|----|------------|-----------|----|-----|";  //NOLINT
+  const char *format  = "\n| %3s | %11s "     "| %6s " "| %2s | 0x%04x | %4d x %4d | %24s "                  "| %4d %4d %4d %4d "  "| %4d %4d %4d %4d "  "| %2s | %10s "   "| %9s | %2s | %3s |";  //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];
+    // sdm-layer from client layer stack
+    Layer *sdm_layer = hw_layers_.info.stack->layers.at(layer_index);
+    // hw-layer from hw layers info
+    Layer &hw_layer = hw_layers_.info.hw_layers.at(i);
+    LayerBuffer *input_buffer = &hw_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(sdm_layer->composition);
+    const char *buffer_format = GetFormatString(input_buffer->format);
+    const char *rotate_split[2] = { "Rot-1", "Rot-2" };
+    const char *comp_split[2] = { "Comp-1", "Comp-2" };
+
+    snprintf(idx, sizeof(idx), "%d", layer_index);
+
+    for (uint32_t count = 0; count < hw_rotator_session.hw_block_count; count++) {
+      char writeback_id[8] = { 0 };
+      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 = GetFormatString(input_buffer->format);
+    }
+
+    for (uint32_t count = 0; count < 2; count++) {
+      char decimation[16] = { 0 };
+      char flags[16] = { 0 };
+      char z_order[8] = { 0 };
+      char color_primary[8] = { 0 };
+      char range[8] = { 0 };
+
+      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", hw_layer.flags.flags);
+      snprintf(decimation, sizeof(decimation), "%3d x %3d", pipe.horizontal_decimation,
+               pipe.vertical_decimation);
+      ColorMetaData &color_metadata = hw_layer.input_buffer.color_metadata;
+      snprintf(color_primary, sizeof(color_primary), "%d", color_metadata.colorPrimaries);
+      snprintf(range, sizeof(range), "%d", color_metadata.range);
+
+      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, color_primary, range);
+
+      // print the below only once per layer block, fill with spaces for rest.
+      idx[0] = 0;
+      comp_type = "";
+    }
+
+    DumpImpl::AppendString(buffer, length, newline);
+  }
+}
+
+const char * DisplayBase::GetName(const LayerComposition &composition) {
+  switch (composition) {
+  case kCompositionGPU:         return "GPU";
+  case kCompositionSDE:         return "SDE";
+  case kCompositionCursor:      return "CURSOR";
+  case kCompositionHybrid:      return "HYBRID";
+  case kCompositionBlit:        return "BLIT";
+  case kCompositionGPUTarget:   return "GPU_TARGET";
+  case kCompositionBlitTarget:  return "BLIT_TARGET";
+  default:                      return "UNKNOWN";
+  }
+}
+
+DisplayError DisplayBase::ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+                                               PPDisplayAPIPayload *out_payload,
+                                               PPPendingParams *pending_action) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (color_mgr_)
+    return color_mgr_->ColorSVCRequestRoute(in_payload, out_payload, pending_action);
+  else
+    return kErrorParameters;
+}
+
+DisplayError DisplayBase::GetColorModeCount(uint32_t *mode_count) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (!mode_count) {
+    return kErrorParameters;
+  }
+
+  if (!color_mgr_) {
+    return kErrorNotSupported;
+  }
+
+  DLOGV_IF(kTagQDCM, "Number of modes from color manager = %d", num_color_modes_);
+  *mode_count = num_color_modes_;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetColorModes(uint32_t *mode_count,
+                                        std::vector<std::string> *color_modes) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (!mode_count || !color_modes) {
+    return kErrorParameters;
+  }
+
+  if (!color_mgr_) {
+    return kErrorNotSupported;
+  }
+
+  for (uint32_t i = 0; i < num_color_modes_; i++) {
+    DLOGV_IF(kTagQDCM, "Color Mode[%d]: Name = %s mode_id = %d", i, color_modes_[i].name,
+             color_modes_[i].id);
+    color_modes->at(i) = color_modes_[i].name;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetColorModeAttr(const std::string &color_mode, AttrVal *attr) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (!attr) {
+    return kErrorParameters;
+  }
+
+  if (!color_mgr_) {
+    return kErrorNotSupported;
+  }
+
+  auto it = color_mode_attr_map_.find(color_mode);
+  if (it == color_mode_attr_map_.end()) {
+    DLOGE("Failed: Mode %s without attribute", color_mode.c_str());
+    return kErrorNotSupported;
+  }
+  *attr = it->second;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::SetColorMode(const std::string &color_mode) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (!color_mgr_) {
+    return kErrorNotSupported;
+  }
+
+  DynamicRangeType dynamic_range_type;
+  if (IsSupportColorModeAttribute(color_mode)) {
+    auto it_mode = color_mode_attr_map_.find(color_mode);
+    std::string dynamic_range;
+    GetValueOfModeAttribute(it_mode->second, kDynamicRangeAttribute, &dynamic_range);
+    if (dynamic_range == kHdr) {
+      dynamic_range_type = kHdrType;
+    } else {
+      dynamic_range_type = kSdrType;
+    }
+  } else {
+    if (color_mode.find("hal_hdr") != std::string::npos) {
+      dynamic_range_type = kHdrType;
+    } else {
+      dynamic_range_type = kSdrType;
+    }
+  }
+
+  DisplayError error = kErrorNone;
+  if (disable_hdr_lut_gen_) {
+    error = SetColorModeInternal(color_mode);
+    if (error != kErrorNone) {
+      return error;
+    }
+    // Store the new SDR color mode request by client
+    if (dynamic_range_type == kSdrType) {
+      current_color_mode_ = color_mode;
+    }
+    return error;
+  }
+
+  if (hdr_playback_mode_) {
+    // HDR playback on, If incoming mode is SDR mode,
+    // cache the mode and apply it after HDR playback stop.
+    if (dynamic_range_type == kHdrType) {
+      error = SetColorModeInternal(color_mode);
+      if (error != kErrorNone) {
+        return error;
+      }
+    } else if (dynamic_range_type == kSdrType) {
+      current_color_mode_ = color_mode;
+    }
+  } else {
+    // HDR playback off, do not apply HDR mode
+    if (dynamic_range_type == kHdrType) {
+      DLOGE("Failed: Forbid setting HDR Mode : %s when HDR playback off", color_mode.c_str());
+      return kErrorNotSupported;
+    }
+    error = SetColorModeInternal(color_mode);
+    if (error != kErrorNone) {
+      return error;
+    }
+    current_color_mode_ = color_mode;
+  }
+
+  return error;
+}
+
+DisplayError DisplayBase::SetColorModeById(int32_t color_mode_id) {
+  return color_mgr_->ColorMgrSetMode(color_mode_id);
+}
+
+DisplayError DisplayBase::SetColorModeInternal(const std::string &color_mode) {
+  DLOGV_IF(kTagQDCM, "Color Mode = %s", color_mode.c_str());
+
+  ColorModeMap::iterator it = color_mode_map_.find(color_mode);
+  if (it == color_mode_map_.end()) {
+    DLOGE("Failed: Unknown Mode : %s", color_mode.c_str());
+    return kErrorNotSupported;
+  }
+
+  SDEDisplayMode *sde_display_mode = it->second;
+
+  DLOGV_IF(kTagQDCM, "Color Mode Name = %s corresponding mode_id = %d", sde_display_mode->name,
+           sde_display_mode->id);
+  DisplayError error = kErrorNone;
+  error = color_mgr_->ColorMgrSetMode(sde_display_mode->id);
+  if (error != kErrorNone) {
+    DLOGE("Failed for mode id = %d", sde_display_mode->id);
+    return error;
+  }
+
+  return error;
+}
+
+DisplayError DisplayBase::GetValueOfModeAttribute(const AttrVal &attr, const std::string &type,
+                                                  std::string *value) {
+  if (!value) {
+    return kErrorParameters;
+  }
+  for (auto &it : attr) {
+    if (it.first.find(type) != std::string::npos) {
+      *value = it.second;
+    }
+  }
+
+  return kErrorNone;
+}
+
+bool DisplayBase::IsSupportColorModeAttribute(const std::string &color_mode) {
+  auto it = color_mode_attr_map_.find(color_mode);
+  if (it == color_mode_attr_map_.end()) {
+    return false;
+  }
+  return true;
+}
+
+DisplayError DisplayBase::GetHdrColorMode(std::string *color_mode, bool *found_hdr) {
+  if (!found_hdr || !color_mode) {
+    return kErrorParameters;
+  }
+  auto it_mode = color_mode_attr_map_.find(current_color_mode_);
+  if (it_mode == color_mode_attr_map_.end()) {
+    DLOGE("Failed: Unknown Mode : %s", current_color_mode_.c_str());
+    return kErrorNotSupported;
+  }
+
+  *found_hdr = false;
+  std::string cur_color_gamut, cur_pic_quality;
+  // get the attributes of current color mode
+  GetValueOfModeAttribute(it_mode->second, kColorGamutAttribute, &cur_color_gamut);
+  GetValueOfModeAttribute(it_mode->second, kPictureQualityAttribute, &cur_pic_quality);
+
+  // found the corresponding HDR mode id which
+  // has the same attributes with current SDR mode.
+  for (auto &it_hdr : color_mode_attr_map_) {
+    std::string dynamic_range, color_gamut, pic_quality;
+    GetValueOfModeAttribute(it_hdr.second, kDynamicRangeAttribute, &dynamic_range);
+    GetValueOfModeAttribute(it_hdr.second, kColorGamutAttribute, &color_gamut);
+    GetValueOfModeAttribute(it_hdr.second, kPictureQualityAttribute, &pic_quality);
+    if (dynamic_range == kHdr && cur_color_gamut == color_gamut &&
+        cur_pic_quality == pic_quality) {
+      *color_mode = it_hdr.first;
+      *found_hdr = true;
+      DLOGV_IF(kTagQDCM, "corresponding hdr mode  = %s", color_mode->c_str());
+      return kErrorNone;
+    }
+  }
+
+  // The corresponding HDR mode was not be found,
+  // apply the first HDR mode that we encouter.
+  for (auto &it_hdr : color_mode_attr_map_) {
+    std::string dynamic_range;
+    GetValueOfModeAttribute(it_hdr.second, kDynamicRangeAttribute, &dynamic_range);
+    if (dynamic_range == kHdr) {
+      *color_mode = it_hdr.first;
+      *found_hdr = true;
+      DLOGV_IF(kTagQDCM, "First hdr mode = %s", color_mode->c_str());
+      return kErrorNone;
+    }
+  }
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::SetColorTransform(const uint32_t length, const double *color_transform) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (!color_mgr_) {
+    return kErrorNotSupported;
+  }
+
+  if (!color_transform) {
+    return kErrorParameters;
+  }
+
+  return color_mgr_->ColorMgrSetColorTransform(length, color_transform);
+}
+
+DisplayError DisplayBase::GetDefaultColorMode(std::string *color_mode) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (!color_mode) {
+    return kErrorParameters;
+  }
+
+  if (!color_mgr_) {
+    return kErrorNotSupported;
+  }
+
+  int32_t default_id = kInvalidModeId;
+  DisplayError error = color_mgr_->ColorMgrGetDefaultModeID(&default_id);
+  if (error != kErrorNone) {
+    DLOGE("Failed for get default color mode id");
+    return error;
+  }
+
+  for (uint32_t i = 0; i < num_color_modes_; i++) {
+    if (color_modes_[i].id == default_id) {
+      *color_mode = color_modes_[i].name;
+      return kErrorNone;
+    }
+  }
+
+  return kErrorNotSupported;
+}
+
+DisplayError DisplayBase::ApplyDefaultDisplayMode() {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (color_mgr_)
+    return color_mgr_->ApplyDefaultDisplayMode();
+  else
+    return kErrorParameters;
+}
+
+DisplayError DisplayBase::SetCursorPosition(int x, int y) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (state_ != kStateOn) {
+    return kErrorNotSupported;
+  }
+
+  DisplayError error = comp_manager_->ValidateCursorPosition(display_comp_ctx_, &hw_layers_, x, y);
+  if (error == kErrorNone) {
+    return hw_intf_->SetCursorPosition(&hw_layers_, x, y);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetRefreshRateRange(uint32_t *min_refresh_rate,
+                                              uint32_t *max_refresh_rate) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  // The min and max refresh rates will be same when the HWPanelInfo does not contain valid rates.
+  // Usually for secondary displays, command mode panels
+  HWDisplayAttributes display_attributes;
+  uint32_t active_index = 0;
+  hw_intf_->GetActiveConfig(&active_index);
+  DisplayError error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
+  if (error) {
+    return error;
+  }
+
+  *min_refresh_rate = display_attributes.fps;
+  *max_refresh_rate = display_attributes.fps;
+
+  return error;
+}
+
+DisplayError DisplayBase::SetVSyncState(bool enable) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+  if (vsync_enable_ != enable) {
+    error = hw_intf_->SetVSyncState(enable);
+    if (error == kErrorNotSupported) {
+      error = hw_events_intf_->SetEventState(HWEvent::VSYNC, enable);
+    }
+    if (error == kErrorNone) {
+      vsync_enable_ = enable;
+    }
+  }
+
+  return error;
+}
+
+DisplayError DisplayBase::ReconfigureDisplay() {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+  HWDisplayAttributes display_attributes;
+  HWMixerAttributes mixer_attributes;
+  HWPanelInfo hw_panel_info;
+  uint32_t active_index = 0;
+
+  error = hw_intf_->GetActiveConfig(&active_index);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = hw_intf_->GetMixerAttributes(&mixer_attributes);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = hw_intf_->GetHWPanelInfo(&hw_panel_info);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  if (display_attributes == display_attributes_ && mixer_attributes == mixer_attributes_ &&
+      hw_panel_info == hw_panel_info_) {
+    return kErrorNone;
+  }
+
+  error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info,
+                                            mixer_attributes, fb_config_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  if (mixer_attributes != mixer_attributes_) {
+    DisablePartialUpdateOneFrame();
+  }
+
+  display_attributes_ = display_attributes;
+  mixer_attributes_ = mixer_attributes;
+  hw_panel_info_ = hw_panel_info;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::SetMixerResolution(uint32_t width, uint32_t height) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  DisplayError error = ReconfigureMixer(width, height);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  req_mixer_width_ = width;
+  req_mixer_height_ = height;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetMixerResolution(uint32_t *width, uint32_t *height) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (!width || !height) {
+    return kErrorParameters;
+  }
+
+  *width = mixer_attributes_.width;
+  *height = mixer_attributes_.height;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::ReconfigureMixer(uint32_t width, uint32_t height) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+
+  if (!width || !height) {
+    return kErrorParameters;
+  }
+
+  HWMixerAttributes mixer_attributes;
+  mixer_attributes.width = width;
+  mixer_attributes.height = height;
+
+  error = hw_intf_->SetMixerAttributes(mixer_attributes);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return ReconfigureDisplay();
+}
+
+bool DisplayBase::NeedsDownScale(const LayerRect &src_rect, const LayerRect &dst_rect,
+                                 bool needs_rotation) {
+  float src_width = FLOAT(src_rect.right - src_rect.left);
+  float src_height = FLOAT(src_rect.bottom - src_rect.top);
+  float dst_width = FLOAT(dst_rect.right - dst_rect.left);
+  float dst_height = FLOAT(dst_rect.bottom - dst_rect.top);
+
+  if (needs_rotation) {
+    std::swap(src_width, src_height);
+  }
+
+  if ((src_width > dst_width) || (src_height > dst_height)) {
+    return true;
+  }
+
+  return false;
+}
+
+bool DisplayBase::NeedsMixerReconfiguration(LayerStack *layer_stack, uint32_t *new_mixer_width,
+                                            uint32_t *new_mixer_height) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  uint32_t layer_count = UINT32(layer_stack->layers.size());
+
+  uint32_t fb_width  = fb_config_.x_pixels;
+  uint32_t fb_height  = fb_config_.y_pixels;
+  uint32_t fb_area = fb_width * fb_height;
+  LayerRect fb_rect = (LayerRect) {0.0f, 0.0f, FLOAT(fb_width), FLOAT(fb_height)};
+  uint32_t mixer_width = mixer_attributes_.width;
+  uint32_t mixer_height = mixer_attributes_.height;
+  uint32_t display_width = display_attributes_.x_pixels;
+  uint32_t display_height = display_attributes_.y_pixels;
+
+  RectOrientation fb_orientation = GetOrientation(fb_rect);
+  uint32_t max_layer_area = 0;
+  uint32_t max_area_layer_index = 0;
+  std::vector<Layer *> layers = layer_stack->layers;
+  uint32_t align_x = display_attributes_.is_device_split ? 4 : 2;
+  uint32_t align_y = 2;
+
+  if (req_mixer_width_ && req_mixer_height_) {
+    *new_mixer_width = req_mixer_width_;
+    *new_mixer_height = req_mixer_height_;
+
+    return (req_mixer_width_ != mixer_width || req_mixer_height_ != mixer_height);
+  }
+
+  for (uint32_t i = 0; i < layer_count; i++) {
+    Layer *layer = layers.at(i);
+
+    uint32_t layer_width = UINT32(layer->src_rect.right - layer->src_rect.left);
+    uint32_t layer_height = UINT32(layer->src_rect.bottom - layer->src_rect.top);
+    uint32_t layer_area = layer_width * layer_height;
+
+    if (layer_area > max_layer_area) {
+      max_layer_area = layer_area;
+      max_area_layer_index = i;
+    }
+  }
+
+  // TODO(user): Mark layer which needs downscaling on GPU fallback as priority layer and use MDP
+  // for composition to avoid quality mismatch between GPU and MDP switch(idle timeout usecase).
+  if (max_layer_area >= fb_area) {
+    Layer *layer = layers.at(max_area_layer_index);
+    bool needs_rotation = (layer->transform.rotation == 90.0f);
+
+    uint32_t layer_width = UINT32(layer->src_rect.right - layer->src_rect.left);
+    uint32_t layer_height = UINT32(layer->src_rect.bottom - layer->src_rect.top);
+    LayerRect layer_dst_rect = {};
+
+    RectOrientation layer_orientation = GetOrientation(layer->src_rect);
+    if (layer_orientation != kOrientationUnknown &&
+        fb_orientation != kOrientationUnknown) {
+      if (layer_orientation != fb_orientation) {
+        std::swap(layer_width, layer_height);
+      }
+    }
+
+    // Align the width and height according to fb's aspect ratio
+    *new_mixer_width = FloorToMultipleOf(UINT32((FLOAT(fb_width) / FLOAT(fb_height)) *
+                                         layer_height), align_x);
+    *new_mixer_height = FloorToMultipleOf(layer_height, align_y);
+
+    LayerRect dst_domain = {0.0f, 0.0f, FLOAT(*new_mixer_width), FLOAT(*new_mixer_height)};
+
+    MapRect(fb_rect, dst_domain, layer->dst_rect, &layer_dst_rect);
+    if (NeedsDownScale(layer->src_rect, layer_dst_rect, needs_rotation)) {
+      *new_mixer_width = display_width;
+      *new_mixer_height = display_height;
+    }
+
+    return true;
+  }
+
+  return false;
+}
+
+DisplayError DisplayBase::SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  uint32_t width = variable_info.x_pixels;
+  uint32_t height = variable_info.y_pixels;
+
+  if (width == 0 || height == 0) {
+    DLOGE("Unsupported resolution: (%dx%d)", width, height);
+    return kErrorParameters;
+  }
+
+  // Create rects to represent the new source and destination crops
+  LayerRect crop = LayerRect(0, 0, FLOAT(width), FLOAT(height));
+  LayerRect dst = LayerRect(0, 0, FLOAT(mixer_attributes_.width), FLOAT(mixer_attributes_.height));
+  // Set rotate90 to false since this is taken care of during regular composition.
+  bool rotate90 = false;
+
+  DisplayError error = comp_manager_->ValidateScaling(crop, dst, rotate90);
+  if (error != kErrorNone) {
+    DLOGE("Unsupported resolution: (%dx%d)", width, height);
+    return kErrorParameters;
+  }
+
+  error =  comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes_, hw_panel_info_,
+                                             mixer_attributes_, variable_info);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  fb_config_.x_pixels = width;
+  fb_config_.y_pixels = height;
+
+  DLOGI("New framebuffer resolution (%dx%d)", fb_config_.x_pixels, fb_config_.y_pixels);
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (!variable_info) {
+    return kErrorParameters;
+  }
+
+  *variable_info = fb_config_;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = comp_manager_->SetDetailEnhancerData(display_comp_ctx_, de_data);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  DisablePartialUpdateOneFrame();
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetDisplayPort(DisplayPort *port) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  if (!port) {
+    return kErrorParameters;
+  }
+
+  *port = hw_panel_info_.port;
+
+  return kErrorNone;
+}
+
+bool DisplayBase::IsPrimaryDisplay() {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  return hw_panel_info_.is_primary_panel;
+}
+
+DisplayError DisplayBase::SetCompositionState(LayerComposition composition_type, bool enable) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  return comp_manager_->SetCompositionState(display_comp_ctx_, composition_type, enable);
+}
+
+void DisplayBase::CommitLayerParams(LayerStack *layer_stack) {
+  // Copy the acquire fence from clients layers  to HWLayers
+  uint32_t hw_layers_count = UINT32(hw_layers_.info.hw_layers.size());
+
+  for (uint32_t i = 0; i < hw_layers_count; i++) {
+    Layer *sdm_layer = layer_stack->layers.at(hw_layers_.info.index[i]);
+    Layer &hw_layer = hw_layers_.info.hw_layers.at(i);
+
+    hw_layer.input_buffer.planes[0].fd = sdm_layer->input_buffer.planes[0].fd;
+    hw_layer.input_buffer.planes[0].offset = sdm_layer->input_buffer.planes[0].offset;
+    hw_layer.input_buffer.planes[0].stride = sdm_layer->input_buffer.planes[0].stride;
+    hw_layer.input_buffer.size = sdm_layer->input_buffer.size;
+    hw_layer.input_buffer.acquire_fence_fd = sdm_layer->input_buffer.acquire_fence_fd;
+  }
+
+  return;
+}
+
+void DisplayBase::PostCommitLayerParams(LayerStack *layer_stack) {
+  // Copy the release fence from HWLayers to clients layers
+    uint32_t hw_layers_count = UINT32(hw_layers_.info.hw_layers.size());
+
+  std::vector<uint32_t> fence_dup_flag;
+
+  for (uint32_t i = 0; i < hw_layers_count; i++) {
+    uint32_t sdm_layer_index = hw_layers_.info.index[i];
+    Layer *sdm_layer = layer_stack->layers.at(sdm_layer_index);
+    Layer &hw_layer = hw_layers_.info.hw_layers.at(i);
+
+    // Copy the release fence only once for a SDM Layer.
+    // In S3D use case, two hw layers can share the same input buffer, So make sure to merge the
+    // output fence fd and assign it to layer's input buffer release fence fd.
+    if (std::find(fence_dup_flag.begin(), fence_dup_flag.end(), sdm_layer_index) ==
+        fence_dup_flag.end()) {
+      sdm_layer->input_buffer.release_fence_fd = hw_layer.input_buffer.release_fence_fd;
+      fence_dup_flag.push_back(sdm_layer_index);
+    } else {
+      int temp = -1;
+      buffer_sync_handler_->SyncMerge(hw_layer.input_buffer.release_fence_fd,
+                                      sdm_layer->input_buffer.release_fence_fd, &temp);
+
+      if (hw_layer.input_buffer.release_fence_fd >= 0) {
+        Sys::close_(hw_layer.input_buffer.release_fence_fd);
+        hw_layer.input_buffer.release_fence_fd = -1;
+      }
+
+      if (sdm_layer->input_buffer.release_fence_fd >= 0) {
+        Sys::close_(sdm_layer->input_buffer.release_fence_fd);
+        sdm_layer->input_buffer.release_fence_fd = -1;
+      }
+
+      sdm_layer->input_buffer.release_fence_fd = temp;
+    }
+
+    // Reset the sync fence fds of HWLayer
+    hw_layer.input_buffer.acquire_fence_fd = -1;
+    hw_layer.input_buffer.release_fence_fd = -1;
+  }
+
+  return;
+}
+
+DisplayError DisplayBase::InitializeColorModes() {
+  if (!color_mgr_) {
+    return kErrorNotSupported;
+  }
+
+  DisplayError error = color_mgr_->ColorMgrGetNumOfModes(&num_color_modes_);
+  if (error != kErrorNone || !num_color_modes_) {
+    DLOGV_IF(kTagQDCM, "GetNumModes failed = %d count = %d", error, num_color_modes_);
+    return kErrorNotSupported;
+  }
+  DLOGI("Number of Color Modes = %d", num_color_modes_);
+
+  if (!color_modes_.size()) {
+    color_modes_.resize(num_color_modes_);
+
+    DisplayError error = color_mgr_->ColorMgrGetModes(&num_color_modes_, color_modes_.data());
+    if (error != kErrorNone) {
+      color_modes_.clear();
+      DLOGE("Failed");
+      return error;
+    }
+    int32_t default_id = kInvalidModeId;
+    error = color_mgr_->ColorMgrGetDefaultModeID(&default_id);
+
+    AttrVal var;
+    for (uint32_t i = 0; i < num_color_modes_; i++) {
+      DLOGV_IF(kTagQDCM, "Color Mode[%d]: Name = %s mode_id = %d", i, color_modes_[i].name,
+               color_modes_[i].id);
+      // get the name of default color mode
+      if (color_modes_[i].id == default_id) {
+        current_color_mode_ = color_modes_[i].name;
+      }
+      auto it = color_mode_map_.find(color_modes_[i].name);
+      if (it != color_mode_map_.end()) {
+        if (it->second->id < color_modes_[i].id) {
+          color_mode_map_.erase(it);
+          color_mode_map_.insert(std::make_pair(color_modes_[i].name, &color_modes_[i]));
+        }
+      } else {
+        color_mode_map_.insert(std::make_pair(color_modes_[i].name, &color_modes_[i]));
+      }
+
+      var.clear();
+      error = color_mgr_->ColorMgrGetModeInfo(color_modes_[i].id, &var);
+      if (error != kErrorNone) {
+        DLOGE("Failed for get attributes of mode_id = %d", color_modes_[i].id);
+        continue;
+      }
+      if (!var.empty()) {
+        auto it = color_mode_attr_map_.find(color_modes_[i].name);
+        if (it == color_mode_attr_map_.end()) {
+          color_mode_attr_map_.insert(std::make_pair(color_modes_[i].name, var));
+        }
+      }
+    }
+  }
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::HandleHDR(LayerStack *layer_stack) {
+  DisplayError error = kErrorNone;
+
+  if (display_type_ != kPrimary) {
+    // Handling is needed for only primary displays
+    return kErrorNone;
+  }
+
+  if (!layer_stack->flags.hdr_present) {
+    //  HDR playback off - set prev mode
+    if (hdr_playback_mode_) {
+      hdr_playback_mode_ = false;
+      if (color_mgr_ && !disable_hdr_lut_gen_) {
+        // Do not apply HDR Mode when hdr lut generation is disabled
+        DLOGI("Setting color mode = %s", current_color_mode_.c_str());
+        // HDR playback off - set prev mode
+        error = SetColorModeInternal(current_color_mode_);
+      }
+      comp_manager_->ControlDpps(true);  // Enable Dpps
+    }
+  } else {
+    // hdr is present
+    if (!hdr_playback_mode_ && !layer_stack->flags.animating) {
+      // hdr is starting
+      hdr_playback_mode_ = true;
+      if (color_mgr_ && !disable_hdr_lut_gen_) {
+        std::string hdr_color_mode;
+        if (IsSupportColorModeAttribute(current_color_mode_)) {
+          bool found_hdr = false;
+          error = GetHdrColorMode(&hdr_color_mode, &found_hdr);
+          // try to set "hal-hdr" mode if did not found that
+          // the dynamic range of mode is hdr
+          if (!found_hdr) {
+            hdr_color_mode = "hal_hdr";
+          }
+        } else {
+          hdr_color_mode = "hal_hdr";
+        }
+        DLOGI("Setting color mode = %s", hdr_color_mode.c_str());
+        error = SetColorModeInternal(hdr_color_mode);
+      }
+      comp_manager_->ControlDpps(false);  // Disable Dpps
+    }
+  }
+
+  return error;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/display_base.h b/sdm845/sdm/libs/core/display_base.h
new file mode 100644
index 0000000..4023229
--- /dev/null
+++ b/sdm845/sdm/libs/core/display_base.h
@@ -0,0 +1,182 @@
+/*
+* Copyright (c) 2014-2017, 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/color_interface.h>
+
+#include <map>
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include "hw_interface.h"
+#include "comp_manager.h"
+#include "color_manager.h"
+#include "hw_events_interface.h"
+
+namespace sdm {
+
+using std::recursive_mutex;
+using std::lock_guard;
+
+class DisplayBase : public DisplayInterface, DumpImpl {
+ public:
+  DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
+              HWDeviceType hw_device_type, BufferSyncHandler *buffer_sync_handler,
+              BufferAllocator *buffer_allocator, CompManager *comp_manager,
+              HWInfoInterface *hw_info_intf);
+  virtual ~DisplayBase() { }
+  virtual DisplayError Init();
+  virtual DisplayError Deinit();
+  DisplayError Prepare(LayerStack *layer_stack);
+  DisplayError Commit(LayerStack *layer_stack);
+  virtual DisplayError Flush();
+  virtual DisplayError GetDisplayState(DisplayState *state);
+  virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
+  virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
+  virtual DisplayError GetConfig(DisplayConfigFixedInfo *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 SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+  virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError DisablePartialUpdateOneFrame() {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError SetDisplayMode(uint32_t mode) {
+    return kErrorNotSupported;
+  }
+  virtual bool IsUnderscanSupported() {
+    return false;
+  }
+  virtual DisplayError SetPanelBrightness(int level) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError CachePanelBrightness(int level) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+                                            PPDisplayAPIPayload *out_payload,
+                                            PPPendingParams *pending_action);
+  virtual DisplayError GetColorModeCount(uint32_t *mode_count);
+  virtual DisplayError GetColorModes(uint32_t *mode_count, std::vector<std::string> *color_modes);
+  virtual DisplayError GetColorModeAttr(const std::string &color_mode, AttrVal *attr);
+  virtual DisplayError SetColorMode(const std::string &color_mode);
+  virtual DisplayError SetColorModeById(int32_t color_mode_id);
+  virtual DisplayError SetColorTransform(const uint32_t length, const double *color_transform);
+  virtual DisplayError GetDefaultColorMode(std::string *color_mode);
+  virtual DisplayError ApplyDefaultDisplayMode(void);
+  virtual DisplayError SetCursorPosition(int x, int y);
+  virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
+  virtual DisplayError GetPanelBrightness(int *level) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError SetVSyncState(bool enable);
+  virtual void SetIdleTimeoutMs(uint32_t active_ms) {}
+  virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height);
+  virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+  virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
+  virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
+  virtual DisplayError SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data);
+  virtual DisplayError GetDisplayPort(DisplayPort *port);
+  virtual bool IsPrimaryDisplay();
+  virtual DisplayError SetCompositionState(LayerComposition composition_type, bool enable);
+
+ protected:
+  DisplayError BuildLayerStackStats(LayerStack *layer_stack);
+  virtual DisplayError ValidateGPUTargetParams();
+  void CommitLayerParams(LayerStack *layer_stack);
+  void PostCommitLayerParams(LayerStack *layer_stack);
+  DisplayError HandleHDR(LayerStack *layer_stack);
+
+  // DumpImpl method
+  void AppendDump(char *buffer, uint32_t length);
+
+  const char *GetName(const LayerComposition &composition);
+  DisplayError ReconfigureDisplay();
+  bool NeedsMixerReconfiguration(LayerStack *layer_stack, uint32_t *new_mixer_width,
+                                 uint32_t *new_mixer_height);
+  DisplayError ReconfigureMixer(uint32_t width, uint32_t height);
+  bool NeedsDownScale(const LayerRect &src_rect, const LayerRect &dst_rect, bool needs_rotation);
+  DisplayError InitializeColorModes();
+  DisplayError SetColorModeInternal(const std::string &color_mode);
+  DisplayError GetValueOfModeAttribute(const AttrVal &attr, const std::string &type,
+                                       std::string *value);
+  DisplayError GetHdrColorMode(std::string *color_mode, bool *found_hdr);
+  bool IsSupportColorModeAttribute(const std::string &color_mode);
+
+  recursive_mutex recursive_mutex_;
+  DisplayType display_type_;
+  DisplayEventHandler *event_handler_ = NULL;
+  HWDeviceType hw_device_type_;
+  HWInterface *hw_intf_ = NULL;
+  HWPanelInfo hw_panel_info_;
+  BufferSyncHandler *buffer_sync_handler_ = NULL;
+  BufferAllocator *buffer_allocator_ {};
+  CompManager *comp_manager_ = NULL;
+  DisplayState state_ = kStateOff;
+  bool active_ = false;
+  Handle hw_device_ = 0;
+  Handle display_comp_ctx_ = 0;
+  HWLayers hw_layers_;
+  bool pending_commit_ = false;
+  bool vsync_enable_ = false;
+  uint32_t max_mixer_stages_ = 0;
+  HWInfoInterface *hw_info_intf_ = NULL;
+  ColorManagerProxy *color_mgr_ = NULL;  // each display object owns its ColorManagerProxy
+  bool partial_update_control_ = true;
+  HWEventsInterface *hw_events_intf_ = NULL;
+  bool disable_pu_one_frame_ = false;
+  uint32_t num_color_modes_ = 0;
+  std::vector<SDEDisplayMode> color_modes_;
+  typedef std::map<std::string, SDEDisplayMode *> ColorModeMap;
+  ColorModeMap color_mode_map_ = {};
+  typedef std::map<std::string, AttrVal> ColorModeAttrMap;
+  ColorModeAttrMap color_mode_attr_map_ = {};
+  HWDisplayAttributes display_attributes_ = {};
+  HWMixerAttributes mixer_attributes_ = {};
+  DisplayConfigVariableInfo fb_config_ = {};
+  uint32_t req_mixer_width_ = 0;
+  uint32_t req_mixer_height_ = 0;
+  std::string current_color_mode_ = "hal_native";
+  bool hdr_playback_mode_ = false;
+  int disable_hdr_lut_gen_ = 0;
+};
+
+}  // namespace sdm
+
+#endif  // __DISPLAY_BASE_H__
diff --git a/sdm845/sdm/libs/core/display_hdmi.cpp b/sdm845/sdm/libs/core/display_hdmi.cpp
new file mode 100644
index 0000000..b31ac94
--- /dev/null
+++ b/sdm845/sdm/libs/core/display_hdmi.cpp
@@ -0,0 +1,313 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <map>
+#include <utility>
+#include <vector>
+
+#include "display_hdmi.h"
+#include "hw_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, BufferAllocator *buffer_allocator,
+                         CompManager *comp_manager)
+  : DisplayBase(kHDMI, event_handler, kDeviceHDMI, buffer_sync_handler, buffer_allocator,
+                comp_manager, hw_info_intf) {
+}
+
+DisplayError DisplayHDMI::Init() {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  DisplayError error = HWInterface::Create(kHDMI, hw_info_intf_, buffer_sync_handler_,
+                                           buffer_allocator_, &hw_intf_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  uint32_t active_mode_index;
+  char value[64] = "0";
+  Debug::GetProperty("sdm.hdmi.s3d_mode", value);
+  HWS3DMode mode = (HWS3DMode)atoi(value);
+  if (mode > kS3DModeNone && mode < kS3DModeMax) {
+    active_mode_index = GetBestConfig(mode);
+  } else {
+    active_mode_index = GetBestConfig(kS3DModeNone);
+  }
+
+  error = hw_intf_->SetDisplayAttributes(active_mode_index);
+  if (error != kErrorNone) {
+    HWInterface::Destroy(hw_intf_);
+  }
+
+  error = DisplayBase::Init();
+  if (error != kErrorNone) {
+    HWInterface::Destroy(hw_intf_);
+    return error;
+  }
+
+  GetScanSupport();
+  underscan_supported_ = (scan_support_ == kScanAlwaysUnderscanned) || (scan_support_ == kScanBoth);
+
+  s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+                            (kS3dFormatNone, kS3DModeNone));
+  s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+                            (kS3dFormatLeftRight, kS3DModeLR));
+  s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+                            (kS3dFormatRightLeft, kS3DModeRL));
+  s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+                            (kS3dFormatTopBottom, kS3DModeTB));
+  s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
+                            (kS3dFormatFramePacking, kS3DModeFP));
+
+  error = HWEventsInterface::Create(INT(display_type_), this, event_list_, &hw_events_intf_);
+  if (error != kErrorNone) {
+    DisplayBase::Deinit();
+    HWInterface::Destroy(hw_intf_);
+    DLOGE("Failed to create hardware events interface. Error = %d", error);
+  }
+
+  current_refresh_rate_ = hw_panel_info_.max_fps;
+
+  return error;
+}
+
+DisplayError DisplayHDMI::Prepare(LayerStack *layer_stack) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+  uint32_t new_mixer_width = 0;
+  uint32_t new_mixer_height = 0;
+  uint32_t display_width = display_attributes_.x_pixels;
+  uint32_t display_height = display_attributes_.y_pixels;
+
+  if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) {
+    error = ReconfigureMixer(new_mixer_width, new_mixer_height);
+    if (error != kErrorNone) {
+      ReconfigureMixer(display_width, display_height);
+    }
+  }
+
+  SetS3DMode(layer_stack);
+
+  // Clean hw layers for reuse.
+  hw_layers_ = HWLayers();
+
+  return DisplayBase::Prepare(layer_stack);
+}
+
+DisplayError DisplayHDMI::GetRefreshRateRange(uint32_t *min_refresh_rate,
+                                              uint32_t *max_refresh_rate) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+
+  if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) {
+    *min_refresh_rate = hw_panel_info_.min_fps;
+    *max_refresh_rate = hw_panel_info_.max_fps;
+  } else {
+    error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
+  }
+
+  return error;
+}
+
+DisplayError DisplayHDMI::SetRefreshRate(uint32_t refresh_rate, bool final_rate) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  if (!active_) {
+    return kErrorPermission;
+  }
+
+  if (current_refresh_rate_ != refresh_rate) {
+    DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
+    if (error != kErrorNone) {
+      return error;
+    }
+  }
+
+  current_refresh_rate_ = refresh_rate;
+  return DisplayBase::ReconfigureDisplay();
+}
+
+bool DisplayHDMI::IsUnderscanSupported() {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  return underscan_supported_;
+}
+
+DisplayError DisplayHDMI::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  return hw_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
+}
+
+uint32_t DisplayHDMI::GetBestConfig(HWS3DMode s3d_mode) {
+  uint32_t best_index = 0, index;
+  uint32_t num_modes = 0;
+  HWDisplayAttributes best_attrib;
+
+  hw_intf_->GetNumDisplayAttributes(&num_modes);
+
+  // Get display attribute for each mode
+  std::vector<HWDisplayAttributes> attrib(num_modes);
+  for (index = 0; index < num_modes; index++) {
+    hw_intf_->GetDisplayAttributes(index, &attrib[index]);
+  }
+
+  // Select best config for s3d_mode. If s3d is not enabled, s3d_mode is kS3DModeNone
+  for (index = 0; index < num_modes; index ++) {
+    if (attrib[index].s3d_config[s3d_mode]) {
+      break;
+    }
+  }
+  if (index < num_modes) {
+    best_index = UINT32(index);
+    for (size_t index = best_index + 1; index < num_modes; index ++) {
+      if (!attrib[index].s3d_config[s3d_mode])
+        continue;
+
+      // From the available configs, select the best
+      // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60
+      if (attrib[index].y_pixels > attrib[best_index].y_pixels) {
+        best_index = UINT32(index);
+      } else if (attrib[index].y_pixels == attrib[best_index].y_pixels) {
+        if (attrib[index].x_pixels > attrib[best_index].x_pixels) {
+          best_index = UINT32(index);
+        } else if (attrib[index].x_pixels == attrib[best_index].x_pixels) {
+          if (attrib[index].vsync_period_ns < attrib[best_index].vsync_period_ns) {
+            best_index = UINT32(index);
+          }
+        }
+      }
+    }
+  } else {
+    DLOGW("%s, could not support S3D mode from EDID info. S3D mode is %d",
+          __FUNCTION__, s3d_mode);
+  }
+
+  // Used for changing HDMI Resolution - override the best with user set config
+  uint32_t user_config = UINT32(Debug::GetHDMIResolution());
+  if (user_config) {
+    uint32_t config_index = 0;
+    // For the config, get the corresponding index
+    DisplayError error = hw_intf_->GetConfigIndex(user_config, &config_index);
+    if (error == kErrorNone)
+      return config_index;
+  }
+
+  return best_index;
+}
+
+void DisplayHDMI::GetScanSupport() {
+  DisplayError error = kErrorNone;
+  uint32_t video_format = 0;
+  uint32_t max_cea_format = 0;
+  HWScanInfo scan_info = HWScanInfo();
+  hw_intf_->GetHWScanInfo(&scan_info);
+
+  uint32_t active_mode_index = 0;
+  hw_intf_->GetActiveConfig(&active_mode_index);
+
+  error = hw_intf_->GetVideoFormat(active_mode_index, &video_format);
+  if (error != kErrorNone) {
+    return;
+  }
+
+  error = hw_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::SetS3DMode(LayerStack *layer_stack) {
+  uint32_t s3d_layer_count = 0;
+  HWS3DMode s3d_mode = kS3DModeNone;
+  uint32_t layer_count = UINT32(layer_stack->layers.size());
+
+  // S3D mode is supported for the following scenarios:
+  // 1. Layer stack containing only one s3d layer which is not skip
+  // 2. Layer stack containing only one secure layer along with one s3d layer
+  for (uint32_t i = 0; i < layer_count; i++) {
+    Layer *layer = layer_stack->layers.at(i);
+    LayerBuffer &layer_buffer = layer->input_buffer;
+
+    if (layer_buffer.s3d_format != kS3dFormatNone) {
+      s3d_layer_count++;
+      if (s3d_layer_count > 1 || layer->flags.skip) {
+        s3d_mode = kS3DModeNone;
+        break;
+      }
+
+      std::map<LayerBufferS3DFormat, HWS3DMode>::iterator it =
+                s3d_format_to_mode_.find(layer_buffer.s3d_format);
+      if (it != s3d_format_to_mode_.end()) {
+        s3d_mode = it->second;
+      }
+    } else if (layer_buffer.flags.secure && layer_count > 2) {
+        s3d_mode = kS3DModeNone;
+        break;
+    }
+  }
+
+  if (hw_intf_->SetS3DMode(s3d_mode) != kErrorNone) {
+    hw_intf_->SetS3DMode(kS3DModeNone);
+    layer_stack->flags.s3d_mode_present = false;
+  } else if (s3d_mode != kS3DModeNone) {
+    layer_stack->flags.s3d_mode_present = true;
+  }
+
+  DisplayBase::ReconfigureDisplay();
+}
+
+void DisplayHDMI::CECMessage(char *message) {
+  event_handler_->CECMessage(message);
+}
+
+DisplayError DisplayHDMI::VSync(int64_t timestamp) {
+  if (vsync_enable_) {
+    DisplayEventVSync vsync;
+    vsync.timestamp = timestamp;
+    event_handler_->VSync(vsync);
+  }
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/core/display_hdmi.h b/sdm845/sdm/libs/core/display_hdmi.h
new file mode 100644
index 0000000..ca09ce3
--- /dev/null
+++ b/sdm845/sdm/libs/core/display_hdmi.h
@@ -0,0 +1,74 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <vector>
+#include <map>
+
+#include "display_base.h"
+#include "dump_impl.h"
+#include "hw_events_interface.h"
+
+namespace sdm {
+
+class HWHDMIInterface;
+
+class DisplayHDMI : public DisplayBase, HWEventHandler {
+ public:
+  DisplayHDMI(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+              BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+              CompManager *comp_manager);
+  virtual DisplayError Init();
+  virtual DisplayError Prepare(LayerStack *layer_stack);
+  virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate, bool final_rate);
+  virtual bool IsUnderscanSupported();
+  virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
+
+  // Implement the HWEventHandlers
+  virtual DisplayError VSync(int64_t timestamp);
+  virtual DisplayError Blank(bool blank) { return kErrorNone; }
+  virtual void IdleTimeout() { }
+  virtual void ThermalEvent(int64_t thermal_level) { }
+  virtual void CECMessage(char *message);
+  virtual void IdlePowerCollapse() { }
+
+ private:
+  uint32_t GetBestConfig(HWS3DMode s3d_mode);
+  void GetScanSupport();
+  void SetS3DMode(LayerStack *layer_stack);
+
+  bool underscan_supported_ = false;
+  HWScanSupport scan_support_;
+  std::map<LayerBufferS3DFormat, HWS3DMode> s3d_format_to_mode_;
+  std::vector<HWEvent> event_list_ = { HWEvent::VSYNC, HWEvent::IDLE_NOTIFY, HWEvent::EXIT,
+    HWEvent::CEC_READ_MESSAGE };
+  uint32_t current_refresh_rate_ = 0;
+};
+
+}  // namespace sdm
+
+#endif  // __DISPLAY_HDMI_H__
diff --git a/sdm845/sdm/libs/core/display_primary.cpp b/sdm845/sdm/libs/core/display_primary.cpp
new file mode 100644
index 0000000..53a4fd9
--- /dev/null
+++ b/sdm845/sdm/libs/core/display_primary.cpp
@@ -0,0 +1,375 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <utils/rect.h>
+#include <map>
+#include <algorithm>
+#include <functional>
+#include <vector>
+
+#include "display_primary.h"
+#include "hw_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,
+                               BufferAllocator *buffer_allocator, CompManager *comp_manager)
+  : DisplayBase(kPrimary, event_handler, kDevicePrimary, buffer_sync_handler, buffer_allocator,
+                comp_manager, hw_info_intf) {
+}
+
+DisplayError DisplayPrimary::Init() {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  DisplayError error = HWInterface::Create(kPrimary, hw_info_intf_, buffer_sync_handler_,
+                                           buffer_allocator_, &hw_intf_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = DisplayBase::Init();
+  if (error != kErrorNone) {
+    HWInterface::Destroy(hw_intf_);
+    return error;
+  }
+
+  if (hw_panel_info_.mode == kModeCommand && Debug::IsVideoModeEnabled()) {
+    error = hw_intf_->SetDisplayMode(kModeVideo);
+    if (error != kErrorNone) {
+      DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode,
+            kModeVideo);
+    }
+  }
+
+  avr_prop_disabled_ = Debug::IsAVRDisabled();
+
+  error = HWEventsInterface::Create(INT(display_type_), this, event_list_, &hw_events_intf_);
+  if (error != kErrorNone) {
+    DLOGE("Failed to create hardware events interface. Error = %d", error);
+    DisplayBase::Deinit();
+    HWInterface::Destroy(hw_intf_);
+  }
+
+  current_refresh_rate_ = hw_panel_info_.max_fps;
+
+  return error;
+}
+
+DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+  uint32_t new_mixer_width = 0;
+  uint32_t new_mixer_height = 0;
+  uint32_t display_width = display_attributes_.x_pixels;
+  uint32_t display_height = display_attributes_.y_pixels;
+  bool needs_hv_flip = hw_panel_info_.panel_orientation.flip_horizontal &&
+                          hw_panel_info_.panel_orientation.flip_vertical;
+  LayerRect src_domain = {};
+  LayerTransform panel_transform = {};
+  DisplayConfigVariableInfo variable_info = {};
+
+  if (needs_hv_flip) {
+    DisplayBase::GetFrameBufferConfig(&variable_info);
+    src_domain.right = variable_info.x_pixels;
+    src_domain.bottom = variable_info.y_pixels;
+    panel_transform.flip_horizontal = hw_panel_info_.panel_orientation.flip_horizontal;
+    panel_transform.flip_vertical = hw_panel_info_.panel_orientation.flip_vertical;
+
+    for (Layer *layer : layer_stack->layers) {
+      // Modify destination based on panel flip
+      TransformHV(src_domain, layer->dst_rect, panel_transform, &layer->dst_rect);
+
+      if (layer->flags.solid_fill) {
+        continue;
+      }
+
+      layer->transform.flip_horizontal ^= (hw_panel_info_.panel_orientation.flip_horizontal);
+      layer->transform.flip_vertical ^= (hw_panel_info_.panel_orientation.flip_vertical);
+     // TODO(user): Check how to handle rotation, if panel has rotation.
+    }
+  }
+
+  if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) {
+    error = ReconfigureMixer(new_mixer_width, new_mixer_height);
+    if (error != kErrorNone) {
+      ReconfigureMixer(display_width, display_height);
+    }
+  }
+
+  // Clean hw layers for reuse.
+  hw_layers_ = HWLayers();
+  hw_layers_.hw_avr_info.enable = NeedsAVREnable();
+
+  return DisplayBase::Prepare(layer_stack);
+}
+
+DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+  uint32_t app_layer_count = hw_layers_.info.app_layer_count;
+
+  // Enabling auto refresh is async and needs to happen before commit ioctl
+  if (hw_panel_info_.mode == kModeCommand) {
+    bool enable = (app_layer_count == 1) && layer_stack->flags.single_buffered_layer_present;
+    bool need_refresh = layer_stack->flags.single_buffered_layer_present && (app_layer_count > 1);
+
+    hw_intf_->SetAutoRefresh(enable);
+    if (need_refresh) {
+      event_handler_->Refresh();
+    }
+  }
+
+  error = DisplayBase::Commit(layer_stack);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  DisplayBase::ReconfigureDisplay();
+
+  int idle_time_ms = hw_layers_.info.set_idle_time_ms;
+  if (idle_time_ms >= 0) {
+    hw_intf_->SetIdleTimeoutMs(UINT32(idle_time_ms));
+  }
+
+  if (switch_to_cmd_) {
+    uint32_t pending;
+    switch_to_cmd_ = false;
+    ControlPartialUpdate(true /* enable */, &pending);
+  }
+
+  return error;
+}
+
+DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+  error = DisplayBase::SetDisplayState(state);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  // Set vsync enable state to false, as driver disables vsync during display power off.
+  if (state == kStateOff) {
+    vsync_enable_ = false;
+  }
+
+  return kErrorNone;
+}
+
+void DisplayPrimary::SetIdleTimeoutMs(uint32_t active_ms) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  if (comp_manager_->SetIdleTimeoutMs(display_comp_ctx_, active_ms) == kErrorNone) {
+    hw_intf_->SetIdleTimeoutMs(active_ms);
+  }
+}
+
+DisplayError DisplayPrimary::SetDisplayMode(uint32_t mode) {
+  DisplayError error = kErrorNone;
+
+  // Limit scope of mutex to this block
+  {
+    lock_guard<recursive_mutex> obj(recursive_mutex_);
+    HWDisplayMode hw_display_mode = static_cast<HWDisplayMode>(mode);
+    uint32_t pending = 0;
+
+    if (!active_) {
+      DLOGW("Invalid display state = %d. Panel must be on.", state_);
+      return kErrorNotSupported;
+    }
+
+    if (hw_display_mode != kModeCommand && hw_display_mode != kModeVideo) {
+      DLOGW("Invalid panel mode parameters. Requested = %d", hw_display_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_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;
+    }
+
+    if (mode == kModeVideo) {
+      ControlPartialUpdate(false /* enable */, &pending);
+    } else if (mode == kModeCommand) {
+      // Flush idle timeout value currently set.
+      hw_intf_->SetIdleTimeoutMs(0);
+      switch_to_cmd_ = true;
+    }
+  }
+
+  // Request for a new draw cycle. New display mode will get applied on next draw cycle.
+  // New idle time will get configured as part of this.
+  event_handler_->Refresh();
+
+  return error;
+}
+
+DisplayError DisplayPrimary::SetPanelBrightness(int level) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  return hw_intf_->SetPanelBrightness(level);
+}
+
+DisplayError DisplayPrimary::CachePanelBrightness(int level) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  return hw_intf_->CachePanelBrightness(level);
+}
+
+DisplayError DisplayPrimary::GetRefreshRateRange(uint32_t *min_refresh_rate,
+                                                 uint32_t *max_refresh_rate) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError error = kErrorNone;
+
+  if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) {
+    *min_refresh_rate = hw_panel_info_.min_fps;
+    *max_refresh_rate = hw_panel_info_.max_fps;
+  } else {
+    error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
+  }
+
+  return error;
+}
+
+DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate, bool final_rate) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  if (!active_ || !hw_panel_info_.dynamic_fps) {
+    return kErrorNotSupported;
+  }
+
+  if (refresh_rate < hw_panel_info_.min_fps || refresh_rate > hw_panel_info_.max_fps) {
+    DLOGE("Invalid Fps = %d request", refresh_rate);
+    return kErrorParameters;
+  }
+
+  if (handle_idle_timeout_ && !final_rate) {
+    refresh_rate = hw_panel_info_.min_fps;
+  }
+
+  if ((current_refresh_rate_ != refresh_rate) || handle_idle_timeout_) {
+    DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
+    if (error != kErrorNone) {
+      return error;
+    }
+  }
+
+  // On success, set current refresh rate to new refresh rate
+  current_refresh_rate_ = refresh_rate;
+  handle_idle_timeout_ = false;
+
+  return DisplayBase::ReconfigureDisplay();
+}
+
+DisplayError DisplayPrimary::VSync(int64_t timestamp) {
+  if (vsync_enable_) {
+    DisplayEventVSync vsync;
+    vsync.timestamp = timestamp;
+    event_handler_->VSync(vsync);
+  }
+
+  return kErrorNone;
+}
+
+void DisplayPrimary::IdleTimeout() {
+  handle_idle_timeout_ = true;
+  event_handler_->Refresh();
+  comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
+}
+
+void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
+}
+
+void DisplayPrimary::IdlePowerCollapse() {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  comp_manager_->ProcessIdlePowerCollapse(display_comp_ctx_);
+}
+
+DisplayError DisplayPrimary::GetPanelBrightness(int *level) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  return hw_intf_->GetPanelBrightness(level);
+}
+
+DisplayError DisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (!pending) {
+    return kErrorParameters;
+  }
+
+  if (!hw_panel_info_.partial_update) {
+    // Nothing to be done.
+    DLOGI("partial update is not applicable for display=%d", display_type_);
+    return kErrorNotSupported;
+  }
+
+  *pending = 0;
+  if (enable == partial_update_control_) {
+    DLOGI("Same state transition is requested.");
+    return kErrorNone;
+  }
+
+  partial_update_control_ = enable;
+
+  if (!enable) {
+    // If the request is to turn off feature, new draw call is required to have
+    // the new setting into effect.
+    *pending = 1;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError DisplayPrimary::DisablePartialUpdateOneFrame() {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  disable_pu_one_frame_ = true;
+
+  return kErrorNone;
+}
+
+bool DisplayPrimary::NeedsAVREnable() {
+  if (avr_prop_disabled_) {
+    return false;
+  }
+
+  return (hw_panel_info_.mode == kModeVideo && ((hw_panel_info_.dynamic_fps &&
+          hw_panel_info_.dfps_porch_mode) || (!hw_panel_info_.dynamic_fps &&
+          hw_panel_info_.min_fps != hw_panel_info_.max_fps)));
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/core/display_primary.h b/sdm845/sdm/libs/core/display_primary.h
new file mode 100644
index 0000000..314964a
--- /dev/null
+++ b/sdm845/sdm/libs/core/display_primary.h
@@ -0,0 +1,79 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <vector>
+
+#include "display_base.h"
+#include "dump_impl.h"
+#include "hw_events_interface.h"
+
+namespace sdm {
+
+class HWPrimaryInterface;
+
+class DisplayPrimary : public DisplayBase, HWEventHandler {
+ public:
+  DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+                 BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+                 CompManager *comp_manager);
+  virtual DisplayError Init();
+  virtual DisplayError Prepare(LayerStack *layer_stack);
+  virtual DisplayError Commit(LayerStack *layer_stack);
+  virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
+  virtual DisplayError DisablePartialUpdateOneFrame();
+  virtual DisplayError SetDisplayState(DisplayState state);
+  virtual void SetIdleTimeoutMs(uint32_t active_ms);
+  virtual DisplayError SetDisplayMode(uint32_t mode);
+  virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate, bool final_rate);
+  virtual DisplayError SetPanelBrightness(int level);
+  virtual DisplayError GetPanelBrightness(int *level);
+  virtual DisplayError CachePanelBrightness(int level);
+
+  // Implement the HWEventHandlers
+  virtual DisplayError VSync(int64_t timestamp);
+  virtual DisplayError Blank(bool blank) { return kErrorNone; }
+  virtual void IdleTimeout();
+  virtual void ThermalEvent(int64_t thermal_level);
+  virtual void CECMessage(char *message) { }
+  virtual void IdlePowerCollapse();
+
+ private:
+  bool NeedsAVREnable();
+
+  std::vector<HWEvent> event_list_ = { HWEvent::VSYNC, HWEvent::EXIT, HWEvent::IDLE_NOTIFY,
+      HWEvent::SHOW_BLANK_EVENT, HWEvent::THERMAL_LEVEL, HWEvent::IDLE_POWER_COLLAPSE };
+  bool avr_prop_disabled_ = false;
+  bool switch_to_cmd_ = false;
+  bool handle_idle_timeout_ = false;
+  uint32_t current_refresh_rate_ = 0;
+};
+
+}  // namespace sdm
+
+#endif  // __DISPLAY_PRIMARY_H__
+
diff --git a/sdm845/sdm/libs/core/display_virtual.cpp b/sdm845/sdm/libs/core/display_virtual.cpp
new file mode 100644
index 0000000..fcdc152
--- /dev/null
+++ b/sdm845/sdm/libs/core/display_virtual.cpp
@@ -0,0 +1,141 @@
+/*
+* Copyright (c) 2014 - 2017, 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_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,
+                               BufferAllocator *buffer_allocator, CompManager *comp_manager)
+  : DisplayBase(kVirtual, event_handler, kDeviceVirtual, buffer_sync_handler, buffer_allocator,
+                comp_manager, hw_info_intf) {
+}
+
+DisplayError DisplayVirtual::Init() {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  DisplayError error = HWInterface::Create(kVirtual, hw_info_intf_, buffer_sync_handler_,
+                                           buffer_allocator_, &hw_intf_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  hw_intf_->GetDisplayAttributes(0 /* active_index */, &display_attributes_);
+
+  error = DisplayBase::Init();
+  if (error != kErrorNone) {
+    HWInterface::Destroy(hw_intf_);
+  }
+
+  return error;
+}
+
+DisplayError DisplayVirtual::GetNumVariableInfoConfigs(uint32_t *count) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  *count = 1;
+  return kErrorNone;
+}
+
+DisplayError DisplayVirtual::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  *variable_info = display_attributes_;
+  return kErrorNone;
+}
+
+DisplayError DisplayVirtual::GetActiveConfig(uint32_t *index) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  *index = 0;
+  return kErrorNone;
+}
+
+DisplayError DisplayVirtual::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  if (!variable_info) {
+    return kErrorParameters;
+  }
+
+  DisplayError error = kErrorNone;
+  HWDisplayAttributes display_attributes;
+  HWMixerAttributes mixer_attributes;
+
+  display_attributes.x_pixels = variable_info->x_pixels;
+  display_attributes.y_pixels = variable_info->y_pixels;
+  display_attributes.fps = variable_info->fps;
+
+  if (display_attributes == display_attributes_) {
+    return kErrorNone;
+  }
+
+  error = hw_intf_->SetDisplayAttributes(display_attributes);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = hw_intf_->GetMixerAttributes(&mixer_attributes);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  // 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_,
+                                         mixer_attributes, fb_config_, &display_comp_ctx_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  display_attributes_ = display_attributes;
+  mixer_attributes_ = mixer_attributes;
+
+  DLOGI("Virtual display resolution changed to[%dx%d]", display_attributes_.x_pixels,
+        display_attributes_.y_pixels);
+
+  return kErrorNone;
+}
+
+DisplayError DisplayVirtual::Prepare(LayerStack *layer_stack) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  // Clean hw layers for reuse.
+  hw_layers_ = HWLayers();
+
+  return DisplayBase::Prepare(layer_stack);
+}
+
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/core/display_virtual.h b/sdm845/sdm/libs/core/display_virtual.h
new file mode 100644
index 0000000..185366c
--- /dev/null
+++ b/sdm845/sdm/libs/core/display_virtual.h
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DISPLAY_VIRTUAL_H__
+#define __DISPLAY_VIRTUAL_H__
+
+#include <private/hw_info_types.h>
+#include "display_base.h"
+#include "dump_impl.h"
+
+namespace sdm {
+
+class HWVirtualInterface;
+
+class DisplayVirtual : public DisplayBase {
+ public:
+  DisplayVirtual(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+                 BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+                 CompManager *comp_manager);
+  virtual DisplayError Init();
+  virtual DisplayError Prepare(LayerStack *layer_stack);
+  virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
+  virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
+  virtual DisplayError GetActiveConfig(uint32_t *index);
+  virtual DisplayError SetActiveConfig(uint32_t index) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info);
+  virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError SetVSyncState(bool enable) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate, bool final_rate) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError ValidateGPUTargetParams() {
+    // TODO(user): Validate GPU target for virtual display when query display attributes
+    // on virtual display is functional.
+    return kErrorNone;
+  }
+};
+
+}  // namespace sdm
+
+#endif  // __DISPLAY_VIRTUAL_H__
+
diff --git a/sdm845/sdm/libs/core/drm/hw_color_manager_drm.cpp b/sdm845/sdm/libs/core/drm/hw_color_manager_drm.cpp
new file mode 100644
index 0000000..640a843
--- /dev/null
+++ b/sdm845/sdm/libs/core/drm/hw_color_manager_drm.cpp
@@ -0,0 +1,294 @@
+/*
+* Copyright (c) 2017, 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 __CLASS__ "HWColorManagerDRM"
+
+#ifdef PP_DRM_ENABLE
+#include <drm/msm_drm_pp.h>
+#endif
+#include <utils/debug.h>
+#include "hw_color_manager_drm.h"
+
+using sde_drm::kFeaturePcc;
+using sde_drm::kFeatureIgc;
+using sde_drm::kFeaturePgc;
+using sde_drm::kFeatureMixerGc;
+using sde_drm::kFeaturePaV2;
+using sde_drm::kFeatureDither;
+using sde_drm::kFeatureGamut;
+using sde_drm::kFeaturePADither;
+using sde_drm::kPPFeaturesMax;
+
+#ifdef PP_DRM_ENABLE
+static const uint32_t kPgcDataMask = 0x3FF;
+static const uint32_t kPgcShift = 16;
+#endif
+
+namespace sdm {
+
+DisplayError (*HWColorManagerDrm::GetDrmFeature[])(const PPFeatureInfo &, DRMPPFeatureInfo *) = {
+        [kGlobalColorFeaturePcc] = &HWColorManagerDrm::GetDrmPCC,
+        [kGlobalColorFeatureIgc] = &HWColorManagerDrm::GetDrmIGC,
+        [kGlobalColorFeaturePgc] = &HWColorManagerDrm::GetDrmPGC,
+        [kMixerColorFeatureGc] = &HWColorManagerDrm::GetDrmMixerGC,
+        [kGlobalColorFeaturePaV2] = &HWColorManagerDrm::GetDrmPAV2,
+        [kGlobalColorFeatureDither] = &HWColorManagerDrm::GetDrmDither,
+        [kGlobalColorFeatureGamut] = &HWColorManagerDrm::GetDrmGamut,
+        [kGlobalColorFeaturePADither] = &HWColorManagerDrm::GetDrmPADither,
+};
+
+void HWColorManagerDrm::FreeDrmFeatureData(DRMPPFeatureInfo *feature) {
+  if (feature->payload)
+    free(feature->payload);
+}
+
+uint32_t HWColorManagerDrm::GetFeatureVersion(const DRMPPFeatureInfo &feature) {
+  uint32_t version = PPFeatureVersion::kSDEPpVersionInvalid;
+
+  switch (feature.id) {
+    case kFeaturePcc:
+      break;
+    case kFeatureIgc:
+      break;
+    case kFeaturePgc:
+      if (feature.version == 1)
+        version = PPFeatureVersion::kSDEPgcV17;
+      break;
+    case kFeatureMixerGc:
+      break;
+    case kFeaturePaV2:
+      break;
+    case kFeatureDither:
+      break;
+    case kFeatureGamut:
+      if (feature.version == 1)
+        version = PPFeatureVersion::kSDEGamutV17;
+      else if (feature.version == 4)
+        version = PPFeatureVersion::kSDEGamutV4;
+      break;
+    case kFeaturePADither:
+      break;
+    default:
+      break;
+  }
+  return version;
+}
+
+DRMPPFeatureID HWColorManagerDrm::ToDrmFeatureId(uint32_t id) {
+  DRMPPFeatureID ret = kPPFeaturesMax;
+
+  switch (id) {
+    case kGlobalColorFeaturePcc:
+      ret = kFeaturePcc;
+      break;
+    case kGlobalColorFeatureIgc:
+      ret = kFeatureIgc;
+      break;
+    case kGlobalColorFeaturePgc:
+      ret = kFeaturePgc;
+      break;
+    case kMixerColorFeatureGc:
+      ret = kFeatureMixerGc;
+      break;
+    case kGlobalColorFeaturePaV2:
+      ret = kFeaturePaV2;
+      break;
+    case kGlobalColorFeatureDither:
+      ret = kFeatureDither;
+      break;
+    case kGlobalColorFeatureGamut:
+      ret = kFeatureGamut;
+      break;
+    case kGlobalColorFeaturePADither:
+      ret = kFeaturePADither;
+      break;
+    default:
+      break;
+  }
+  return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmPCC(const PPFeatureInfo &in_data,
+                                          DRMPPFeatureInfo *out_data) {
+  DisplayError ret = kErrorNone;
+  return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmIGC(const PPFeatureInfo &in_data,
+                                          DRMPPFeatureInfo *out_data) {
+  DisplayError ret = kErrorNone;
+  return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmPGC(const PPFeatureInfo &in_data,
+                                          DRMPPFeatureInfo *out_data) {
+  DisplayError ret = kErrorNone;
+#ifdef PP_DRM_ENABLE
+  struct SDEPgcLUTData *sde_pgc;
+  struct drm_msm_pgc_lut *mdp_pgc;
+
+  if (!out_data) {
+    DLOGE("Invalid input parameter for gamut");
+    return kErrorParameters;
+  }
+  sde_pgc = (struct SDEPgcLUTData *)in_data.GetConfigData();
+  out_data->id = kFeaturePgc;
+  out_data->type = sde_drm::kPropBlob;
+  out_data->version = in_data.feature_version_;
+  out_data->payload_size = sizeof(struct drm_msm_pgc_lut);
+
+  if (in_data.enable_flags_ & kOpsDisable) {
+    /* feature disable case */
+    out_data->payload = NULL;
+    return ret;
+  } else if (!(in_data.enable_flags_ & kOpsEnable)) {
+    out_data->payload = NULL;
+    return kErrorParameters;
+  }
+
+  mdp_pgc = new drm_msm_pgc_lut();
+  if (!mdp_pgc) {
+    DLOGE("Failed to allocate memory for pgc");
+    return kErrorMemory;
+  }
+
+  if (in_data.enable_flags_ & kOpsEnable)
+    mdp_pgc->flags = PGC_8B_ROUND;
+  else
+    mdp_pgc->flags = 0;
+
+  for (int i = 0, j = 0; i < PGC_TBL_LEN; i++, j += 2) {
+    mdp_pgc->c0[i] = (sde_pgc->c0_data[j] & kPgcDataMask) |
+        (sde_pgc->c0_data[j + 1] & kPgcDataMask) << kPgcShift;
+    mdp_pgc->c1[i] = (sde_pgc->c1_data[j] & kPgcDataMask) |
+        (sde_pgc->c1_data[j + 1] & kPgcDataMask) << kPgcShift;
+    mdp_pgc->c2[i] = (sde_pgc->c2_data[j] & kPgcDataMask) |
+        (sde_pgc->c2_data[j + 1] & kPgcDataMask) << kPgcShift;
+  }
+  out_data->payload = mdp_pgc;
+#endif
+  return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmMixerGC(const PPFeatureInfo &in_data,
+                                              DRMPPFeatureInfo *out_data) {
+  DisplayError ret = kErrorNone;
+  return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmPAV2(const PPFeatureInfo &in_data,
+                                           DRMPPFeatureInfo *out_data) {
+  DisplayError ret = kErrorNone;
+  return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmDither(const PPFeatureInfo &in_data,
+                                             DRMPPFeatureInfo *out_data) {
+  DisplayError ret = kErrorNone;
+  return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmGamut(const PPFeatureInfo &in_data,
+                                            DRMPPFeatureInfo *out_data) {
+  DisplayError ret = kErrorNone;
+#ifdef PP_DRM_ENABLE
+  struct SDEGamutCfg *sde_gamut = NULL;
+  struct drm_msm_3d_gamut *mdp_gamut = NULL;
+  uint32_t size = 0;
+
+  if (!out_data) {
+    DLOGE("Invalid input parameter for gamut");
+    return kErrorParameters;
+  }
+  sde_gamut = (struct SDEGamutCfg *)in_data.GetConfigData();
+  out_data->id = kFeatureGamut;
+  out_data->type = sde_drm::kPropBlob;
+  out_data->version = in_data.feature_version_;
+  out_data->payload_size = sizeof(struct drm_msm_3d_gamut);
+  if (in_data.enable_flags_ & kOpsDisable) {
+    /* feature disable case */
+    out_data->payload = NULL;
+    return ret;
+  } else if (!(in_data.enable_flags_ & kOpsEnable)) {
+    out_data->payload = NULL;
+    return kErrorParameters;
+  }
+
+  mdp_gamut = new drm_msm_3d_gamut();
+  if (!mdp_gamut) {
+    DLOGE("Failed to allocate memory for gamut");
+    return kErrorMemory;
+  }
+
+  if (sde_gamut->map_en)
+    mdp_gamut->flags = GAMUT_3D_MAP_EN;
+  else
+    mdp_gamut->flags = 0;
+
+  switch (sde_gamut->mode) {
+    case SDEGamutCfgWrapper::GAMUT_FINE_MODE:
+      mdp_gamut->mode = GAMUT_3D_MODE_17;
+      size = GAMUT_3D_MODE17_TBL_SZ;
+      break;
+    case SDEGamutCfgWrapper::GAMUT_COARSE_MODE:
+      mdp_gamut->mode = GAMUT_3D_MODE_5;
+      size = GAMUT_3D_MODE5_TBL_SZ;
+      break;
+    case SDEGamutCfgWrapper::GAMUT_COARSE_MODE_13:
+      mdp_gamut->mode = GAMUT_3D_MODE_13;
+      size = GAMUT_3D_MODE13_TBL_SZ;
+      break;
+    default:
+      DLOGE("Invalid gamut mode %d", sde_gamut->mode);
+      free(mdp_gamut);
+      return kErrorParameters;
+  }
+
+  if (sde_gamut->map_en)
+    std::memcpy(mdp_gamut->scale_off, sde_gamut->scale_off_data,
+                sizeof(uint32_t) * GAMUT_3D_SCALE_OFF_SZ * GAMUT_3D_SCALE_OFF_TBL_NUM);
+
+  for (uint32_t row = 0; row < GAMUT_3D_TBL_NUM; row++) {
+    for (uint32_t col = 0; col < size; col++) {
+      mdp_gamut->col[row][col].c0 = sde_gamut->c0_data[row][col];
+      mdp_gamut->col[row][col].c2_c1 = sde_gamut->c1_c2_data[row][col];
+    }
+  }
+  out_data->payload = mdp_gamut;
+#endif
+  return ret;
+}
+
+DisplayError HWColorManagerDrm::GetDrmPADither(const PPFeatureInfo &in_data,
+                                               DRMPPFeatureInfo *out_data) {
+  DisplayError ret = kErrorNone;
+  return ret;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/drm/hw_color_manager_drm.h b/sdm845/sdm/libs/core/drm/hw_color_manager_drm.h
new file mode 100644
index 0000000..a10d00b
--- /dev/null
+++ b/sdm845/sdm/libs/core/drm/hw_color_manager_drm.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2017, 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_COLOR_MANAGER_DRM_H__
+#define __HW_COLOR_MANAGER_DRM_H__
+
+#include <drm_interface.h>
+#include <private/color_params.h>
+
+using sde_drm::DRMPPFeatureID;
+using sde_drm::DRMPPFeatureInfo;
+
+namespace sdm {
+
+class HWColorManagerDrm {
+ public:
+  static DisplayError (*GetDrmFeature[kMaxNumPPFeatures])(const PPFeatureInfo &in_data,
+                                                          DRMPPFeatureInfo *out_data);
+  static void FreeDrmFeatureData(DRMPPFeatureInfo *feature);
+  static uint32_t GetFeatureVersion(const DRMPPFeatureInfo &feature);
+  static DRMPPFeatureID ToDrmFeatureId(uint32_t id);
+ protected:
+  HWColorManagerDrm() {}
+
+ private:
+  static DisplayError GetDrmPCC(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+  static DisplayError GetDrmIGC(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+  static DisplayError GetDrmPGC(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+  static DisplayError GetDrmMixerGC(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+  static DisplayError GetDrmPAV2(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+  static DisplayError GetDrmDither(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+  static DisplayError GetDrmGamut(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+  static DisplayError GetDrmPADither(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+};
+
+}  // namespace sdm
+
+#endif  // __HW_COLOR_MANAGER_DRM_H__
diff --git a/sdm845/sdm/libs/core/drm/hw_device_drm.cpp b/sdm845/sdm/libs/core/drm/hw_device_drm.cpp
new file mode 100644
index 0000000..1028663
--- /dev/null
+++ b/sdm845/sdm/libs/core/drm/hw_device_drm.cpp
@@ -0,0 +1,1115 @@
+/*
+* Copyright (c) 2017, 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 <drm/drm_fourcc.h>
+#include <drm_lib_loader.h>
+#include <drm_master.h>
+#include <drm_res_mgr.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <linux/fb.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/formats.h>
+#include <utils/sys.h>
+#include <drm/sde_drm.h>
+#include <private/color_params.h>
+
+#include <algorithm>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "hw_device_drm.h"
+#include "hw_info_interface.h"
+#include "hw_color_manager_drm.h"
+
+#define __CLASS__ "HWDeviceDRM"
+
+#ifndef DRM_FORMAT_MOD_QCOM_COMPRESSED
+#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
+#endif
+#ifndef DRM_FORMAT_MOD_QCOM_DX
+#define DRM_FORMAT_MOD_QCOM_DX fourcc_mod_code(QCOM, 0x2)
+#endif
+#ifndef DRM_FORMAT_MOD_QCOM_TIGHT
+#define DRM_FORMAT_MOD_QCOM_TIGHT fourcc_mod_code(QCOM, 0x4)
+#endif
+
+using std::string;
+using std::to_string;
+using std::fstream;
+using std::unordered_map;
+using drm_utils::DRMMaster;
+using drm_utils::DRMResMgr;
+using drm_utils::DRMLibLoader;
+using drm_utils::DRMBuffer;
+using sde_drm::GetDRMManager;
+using sde_drm::DestroyDRMManager;
+using sde_drm::DRMDisplayType;
+using sde_drm::DRMDisplayToken;
+using sde_drm::DRMConnectorInfo;
+using sde_drm::DRMPPFeatureInfo;
+using sde_drm::DRMRect;
+using sde_drm::DRMRotation;
+using sde_drm::DRMBlendType;
+using sde_drm::DRMSrcConfig;
+using sde_drm::DRMOps;
+using sde_drm::DRMTopology;
+using sde_drm::DRMPowerMode;
+
+namespace sdm {
+
+static void GetDRMFormat(LayerBufferFormat format, uint32_t *drm_format,
+                         uint64_t *drm_format_modifier) {
+  switch (format) {
+    case kFormatRGBA8888:
+      *drm_format = DRM_FORMAT_ABGR8888;
+      break;
+    case kFormatRGBA8888Ubwc:
+      *drm_format = DRM_FORMAT_ABGR8888;
+      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+      break;
+    case kFormatRGBA5551:
+      *drm_format = DRM_FORMAT_ABGR1555;
+      break;
+    case kFormatRGBA4444:
+      *drm_format = DRM_FORMAT_ABGR4444;
+      break;
+    case kFormatBGRA8888:
+      *drm_format = DRM_FORMAT_ARGB8888;
+      break;
+    case kFormatRGBX8888:
+      *drm_format = DRM_FORMAT_XBGR8888;
+      break;
+    case kFormatRGBX8888Ubwc:
+      *drm_format = DRM_FORMAT_XBGR8888;
+      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+      break;
+    case kFormatBGRX8888:
+      *drm_format = DRM_FORMAT_XRGB8888;
+      break;
+    case kFormatRGB888:
+      *drm_format = DRM_FORMAT_BGR888;
+      break;
+    case kFormatRGB565:
+      *drm_format = DRM_FORMAT_BGR565;
+      break;
+    case kFormatBGR565:
+      *drm_format = DRM_FORMAT_RGB565;
+      break;
+    case kFormatBGR565Ubwc:
+      *drm_format = DRM_FORMAT_BGR565;
+      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+      break;
+    case kFormatRGBA1010102:
+      *drm_format = DRM_FORMAT_ABGR2101010;
+      break;
+    case kFormatRGBA1010102Ubwc:
+      *drm_format = DRM_FORMAT_ABGR2101010;
+      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+      break;
+    case kFormatARGB2101010:
+      *drm_format = DRM_FORMAT_BGRA1010102;
+      break;
+    case kFormatRGBX1010102:
+      *drm_format = DRM_FORMAT_XBGR2101010;
+      break;
+    case kFormatRGBX1010102Ubwc:
+      *drm_format = DRM_FORMAT_XBGR2101010;
+      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+      break;
+    case kFormatXRGB2101010:
+      *drm_format = DRM_FORMAT_BGRX1010102;
+      break;
+    case kFormatBGRA1010102:
+      *drm_format = DRM_FORMAT_ARGB2101010;
+      break;
+    case kFormatABGR2101010:
+      *drm_format = DRM_FORMAT_RGBA1010102;
+      break;
+    case kFormatBGRX1010102:
+      *drm_format = DRM_FORMAT_XRGB2101010;
+      break;
+    case kFormatXBGR2101010:
+      *drm_format = DRM_FORMAT_RGBX1010102;
+      break;
+    case kFormatYCbCr420SemiPlanar:
+      *drm_format = DRM_FORMAT_NV12;
+      break;
+    case kFormatYCbCr420SemiPlanarVenus:
+      *drm_format = DRM_FORMAT_NV12;
+      break;
+    case kFormatYCbCr420SPVenusUbwc:
+      *drm_format = DRM_FORMAT_NV12;
+      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+      break;
+    case kFormatYCrCb420SemiPlanar:
+      *drm_format = DRM_FORMAT_NV21;
+      break;
+    case kFormatYCrCb420SemiPlanarVenus:
+      *drm_format = DRM_FORMAT_NV21;
+      break;
+    case kFormatYCbCr420P010:
+      *drm_format = DRM_FORMAT_NV12;
+      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_DX;
+      break;
+    case kFormatYCbCr420P010Ubwc:
+      *drm_format = DRM_FORMAT_NV12;
+      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
+        DRM_FORMAT_MOD_QCOM_DX;
+      break;
+    case kFormatYCbCr420TP10Ubwc:
+      *drm_format = DRM_FORMAT_NV12;
+      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
+        DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_TIGHT;
+      break;
+    case kFormatYCbCr422H2V1SemiPlanar:
+      *drm_format = DRM_FORMAT_NV16;
+      break;
+    case kFormatYCrCb422H2V1SemiPlanar:
+      *drm_format = DRM_FORMAT_NV61;
+      break;
+    case kFormatYCrCb420PlanarStride16:
+      *drm_format = DRM_FORMAT_YVU420;
+      break;
+    default:
+      DLOGW("Unsupported format %s", GetFormatString(format));
+  }
+}
+
+void HWDeviceDRM::Registry::RegisterCurrent(HWLayers *hw_layers) {
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
+
+  for (uint32_t i = 0; i < hw_layer_count; i++) {
+    Layer &layer = hw_layer_info.hw_layers.at(i);
+    LayerBuffer *input_buffer = &layer.input_buffer;
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+    HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[0];
+
+    if (hw_rotate_info->valid) {
+      input_buffer = &hw_rotator_session->output_buffer;
+    }
+
+    MapBufferToFbId(input_buffer);
+  }
+}
+
+void HWDeviceDRM::Registry::MapBufferToFbId(LayerBuffer* buffer) {
+  int fd = buffer->planes[0].fd;
+  DRMMaster *master = nullptr;
+  DRMMaster::GetInstance(&master);
+
+  if (!master) {
+    DLOGE("Failed to acquire DRM Master instance");
+    return;
+  }
+
+  if (fd >= 0 && hashmap_[current_index_].find(fd) == hashmap_[current_index_].end()) {
+    AllocatedBufferInfo buf_info{};
+    DRMBuffer layout{};
+    buf_info.fd = layout.fd = fd;
+    buf_info.aligned_width = layout.width = buffer->width;
+    buf_info.aligned_height = layout.height = buffer->height;
+    buf_info.format = buffer->format;
+    GetDRMFormat(buf_info.format, &layout.drm_format, &layout.drm_format_modifier);
+    buffer_allocator_->GetBufferLayout(buf_info, layout.stride, layout.offset,
+        &layout.num_planes);
+    uint32_t fb_id = 0;
+    int ret = master->CreateFbId(layout, &fb_id);
+    if (ret < 0) {
+      DLOGE("CreateFbId failed. width %d, height %d, format: %s, stride %u, error %d",
+          layout.width, layout.height, GetFormatString(buf_info.format), layout.stride[0],
+          errno);
+    } else {
+      hashmap_[current_index_][fd] = fb_id;
+    }
+  }
+  return;
+}
+
+void HWDeviceDRM::Registry::UnregisterNext() {
+  DRMMaster *master = nullptr;
+  DRMMaster::GetInstance(&master);
+
+  if (!master) {
+    DLOGE("Failed to acquire DRM Master instance");
+    return;
+  }
+
+  current_index_ = (current_index_ + 1) % kCycleDelay;
+  auto &curr_map = hashmap_[current_index_];
+  for (auto &pair : curr_map) {
+    uint32_t fb_id = pair.second;
+    int ret = master->RemoveFbId(fb_id);
+    if (ret < 0) {
+      DLOGE("Removing fb_id %d failed with error %d", fb_id, errno);
+    }
+  }
+
+  curr_map.clear();
+}
+
+void HWDeviceDRM::Registry::Clear() {
+  for (int i = 0; i < kCycleDelay; i++) {
+    UnregisterNext();
+  }
+  current_index_ = 0;
+}
+
+uint32_t HWDeviceDRM::Registry::GetFbId(int fd) {
+  auto it = hashmap_[current_index_].find(fd);
+  return (it == hashmap_[current_index_].end()) ? 0 : it->second;
+}
+
+HWDeviceDRM::HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+                         HWInfoInterface *hw_info_intf)
+    : hw_info_intf_(hw_info_intf), buffer_sync_handler_(buffer_sync_handler),
+      registry_(buffer_allocator) {
+  device_type_ = kDevicePrimary;
+  disp_type_ = DRMDisplayType::PERIPHERAL;
+  device_name_ = "Peripheral Display";
+  hw_info_intf_ = hw_info_intf;
+}
+
+DisplayError HWDeviceDRM::Init() {
+  default_mode_ = (DRMLibLoader::GetInstance()->IsLoaded() == false);
+
+  if (!default_mode_) {
+    DRMMaster *drm_master = {};
+    DRMMaster::GetInstance(&drm_master);
+    drm_master->GetHandle(&dev_fd_);
+    DRMLibLoader::GetInstance()->FuncGetDRMManager()(dev_fd_, &drm_mgr_intf_);
+    if (drm_mgr_intf_->RegisterDisplay(disp_type_, &token_)) {
+      DLOGE("RegisterDisplay failed for display %d", disp_type_);
+      return kErrorResources;
+    }
+    drm_mgr_intf_->CreateAtomicReq(token_, &drm_atomic_intf_);
+    drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
+    InitializeConfigs();
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, &current_mode_);
+
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
+    // Commit to setup pipeline with mode, which then tells us the topology etc
+
+    if (!deferred_initialize_) {
+      if (drm_atomic_intf_->Commit(true /* synchronous */)) {
+        DRM_LOGI("Setting up CRTC %d, Connector %d for %s failed", token_.crtc_id,
+          token_.conn_id, device_name_);
+        return kErrorResources;
+      }
+      // Reload connector info for updated info after 1st commit
+
+      drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
+    }
+  }
+  PopulateDisplayAttributes();
+  PopulateHWPanelInfo();
+  UpdateMixerAttributes();
+  hw_info_intf_->GetHWResourceInfo(&hw_resource_);
+
+  // TODO(user): In future, remove has_qseed3 member, add version and pass version to constructor
+  if (hw_resource_.has_qseed3) {
+    hw_scale_ = new HWScaleDRM(HWScaleDRM::Version::V2);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::Deinit() {
+  delete hw_scale_;
+  registry_.Clear();
+  drm_mgr_intf_->DestroyAtomicReq(drm_atomic_intf_);
+  drm_atomic_intf_ = {};
+  drm_mgr_intf_->UnregisterDisplay(token_);
+  return kErrorNone;
+}
+
+void HWDeviceDRM::InitializeConfigs() {
+  // TODO(user): Update modes
+  current_mode_ = connector_info_.modes[0];
+}
+
+DisplayError HWDeviceDRM::PopulateDisplayAttributes() {
+  drmModeModeInfo mode = {};
+  uint32_t mm_width = 0;
+  uint32_t mm_height = 0;
+  DRMTopology topology = DRMTopology::SINGLE_LM;
+
+  if (default_mode_) {
+    DRMResMgr *res_mgr = nullptr;
+    int ret = DRMResMgr::GetInstance(&res_mgr);
+    if (ret < 0) {
+      DLOGE("Failed to acquire DRMResMgr instance");
+      return kErrorResources;
+    }
+
+    res_mgr->GetMode(&mode);
+    res_mgr->GetDisplayDimInMM(&mm_width, &mm_height);
+  } else {
+    mode = current_mode_;
+    mm_width = connector_info_.mmWidth;
+    mm_height = connector_info_.mmHeight;
+    topology = connector_info_.topology;
+  }
+
+  display_attributes_.x_pixels = mode.hdisplay;
+  display_attributes_.y_pixels = mode.vdisplay;
+  display_attributes_.fps = mode.vrefresh;
+  display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps);
+
+  /*
+              Active                 Front           Sync           Back
+              Region                 Porch                          Porch
+     <-----------------------><----------------><-------------><-------------->
+     <----- [hv]display ----->
+     <------------- [hv]sync_start ------------>
+     <--------------------- [hv]sync_end --------------------->
+     <-------------------------------- [hv]total ----------------------------->
+   */
+
+  display_attributes_.v_front_porch = mode.vsync_start - mode.vdisplay;
+  display_attributes_.v_pulse_width = mode.vsync_end - mode.vsync_start;
+  display_attributes_.v_back_porch = mode.vtotal - mode.vsync_end;
+  display_attributes_.v_total = mode.vtotal;
+
+  display_attributes_.h_total = mode.htotal;
+  uint32_t h_blanking = mode.htotal - mode.hdisplay;
+  display_attributes_.is_device_split =
+      (topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_MERGE);
+  display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0;
+
+  display_attributes_.x_dpi = (FLOAT(mode.hdisplay) * 25.4f) / FLOAT(mm_width);
+  display_attributes_.y_dpi = (FLOAT(mode.vdisplay) * 25.4f) / FLOAT(mm_height);
+
+  return kErrorNone;
+}
+
+void HWDeviceDRM::PopulateHWPanelInfo() {
+  hw_panel_info_ = {};
+
+  snprintf(hw_panel_info_.panel_name, sizeof(hw_panel_info_.panel_name), "%s",
+           connector_info_.panel_name.c_str());
+  hw_panel_info_.split_info.left_split = display_attributes_.x_pixels;
+  if (display_attributes_.is_device_split) {
+    hw_panel_info_.split_info.left_split = hw_panel_info_.split_info.right_split =
+        display_attributes_.x_pixels / 2;
+  }
+
+  hw_panel_info_.partial_update = connector_info_.num_roi;
+  hw_panel_info_.left_roi_count = UINT32(connector_info_.num_roi);
+  hw_panel_info_.right_roi_count = UINT32(connector_info_.num_roi);
+  hw_panel_info_.left_align = connector_info_.xstart;
+  hw_panel_info_.top_align = connector_info_.ystart;
+  hw_panel_info_.width_align = connector_info_.walign;
+  hw_panel_info_.height_align = connector_info_.halign;
+  hw_panel_info_.min_roi_width = connector_info_.wmin;
+  hw_panel_info_.min_roi_height = connector_info_.hmin;
+  hw_panel_info_.needs_roi_merge = connector_info_.roi_merge;
+  hw_panel_info_.dynamic_fps = connector_info_.dynamic_fps;
+  hw_panel_info_.min_fps = 60;
+  hw_panel_info_.max_fps = 60;
+  hw_panel_info_.is_primary_panel = connector_info_.is_primary;
+  hw_panel_info_.is_pluggable = 0;
+
+  // no supprt for 90 rotation only flips or 180 supported
+  hw_panel_info_.panel_orientation.rotation = 0;
+  hw_panel_info_.panel_orientation.flip_horizontal =
+    (connector_info_.panel_orientation == DRMRotation::FLIP_H) ||
+    (connector_info_.panel_orientation == DRMRotation::ROT_180);
+  hw_panel_info_.panel_orientation.flip_vertical =
+    (connector_info_.panel_orientation == DRMRotation::FLIP_V) ||
+    (connector_info_.panel_orientation == DRMRotation::ROT_180);
+
+  GetHWDisplayPortAndMode();
+  GetHWPanelMaxBrightness();
+
+  DLOGI("%s, Panel Interface = %s, Panel Mode = %s, Is Primary = %d", device_name_,
+        interface_str_.c_str(), hw_panel_info_.mode == kModeVideo ? "Video" : "Command",
+        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);
+}
+
+void HWDeviceDRM::GetHWDisplayPortAndMode() {
+  hw_panel_info_.port = kPortDefault;
+  hw_panel_info_.mode =
+      (connector_info_.panel_mode == sde_drm::DRMPanelMode::VIDEO) ? kModeVideo : kModeCommand;
+
+  if (default_mode_) {
+    return;
+  }
+
+  switch (connector_info_.type) {
+    case DRM_MODE_CONNECTOR_DSI:
+      hw_panel_info_.port = kPortDSI;
+      interface_str_ = "DSI";
+      break;
+    case DRM_MODE_CONNECTOR_LVDS:
+      hw_panel_info_.port = kPortLVDS;
+      interface_str_ = "LVDS";
+      break;
+    case DRM_MODE_CONNECTOR_eDP:
+      hw_panel_info_.port = kPortEDP;
+      interface_str_ = "EDP";
+      break;
+    case DRM_MODE_CONNECTOR_TV:
+    case DRM_MODE_CONNECTOR_HDMIA:
+    case DRM_MODE_CONNECTOR_HDMIB:
+      hw_panel_info_.port = kPortDTV;
+      interface_str_ = "HDMI";
+      break;
+    case DRM_MODE_CONNECTOR_VIRTUAL:
+      hw_panel_info_.port = kPortWriteBack;
+      interface_str_ = "Virtual";
+      break;
+    case DRM_MODE_CONNECTOR_DisplayPort:
+      // TODO(user): Add when available
+      interface_str_ = "DisplayPort";
+      break;
+  }
+
+  return;
+}
+
+void HWDeviceDRM::GetHWPanelMaxBrightness() {
+  char brightness[kMaxStringLength] = {0};
+  string kMaxBrightnessNode = "/sys/class/backlight/panel0-backlight/max_brightness";
+
+  hw_panel_info_.panel_max_brightness = 255;
+  int fd = Sys::open_(kMaxBrightnessNode.c_str(), O_RDONLY);
+  if (fd < 0) {
+    DLOGW("Failed to open max brightness node = %s, error = %s", kMaxBrightnessNode.c_str(),
+          strerror(errno));
+    return;
+  }
+
+  if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
+    hw_panel_info_.panel_max_brightness = atoi(brightness);
+    DLOGI("Max brightness level = %d", hw_panel_info_.panel_max_brightness);
+  } else {
+    DLOGW("Failed to read max brightness level. error = %s", strerror(errno));
+  }
+
+  Sys::close_(fd);
+}
+
+DisplayError HWDeviceDRM::GetActiveConfig(uint32_t *active_config) {
+  *active_config = 0;
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::GetNumDisplayAttributes(uint32_t *count) {
+  *count = 1;
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::GetDisplayAttributes(uint32_t index,
+                                            HWDisplayAttributes *display_attributes) {
+  *display_attributes = display_attributes_;
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::GetHWPanelInfo(HWPanelInfo *panel_info) {
+  *panel_info = hw_panel_info_;
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::SetDisplayAttributes(uint32_t index) {
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::GetConfigIndex(uint32_t mode, uint32_t *index) {
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::PowerOn() {
+  DTRACE_SCOPED();
+  drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
+  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::ON);
+  int ret = drm_atomic_intf_->Commit(false /* synchronous */);
+  if (ret) {
+    DLOGE("%s failed with error %d", __FUNCTION__, ret);
+    return kErrorHardware;
+  }
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::PowerOff() {
+  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::OFF);
+  drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 0);
+  int ret = drm_atomic_intf_->Commit(false /* synchronous */);
+  if (ret) {
+    DLOGE("%s failed with error %d", __FUNCTION__, ret);
+    return kErrorHardware;
+  }
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::Doze() {
+  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::DOZE);
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::DozeSuspend() {
+  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id,
+                            DRMPowerMode::DOZE_SUSPEND);
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::Standby() {
+  return kErrorNone;
+}
+
+void HWDeviceDRM::SetupAtomic(HWLayers *hw_layers, bool validate) {
+  if (default_mode_) {
+    return;
+  }
+
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
+
+  // TODO(user): Once destination scalar is enabled we can always send ROIs if driver allows
+  if (hw_panel_info_.partial_update) {
+    const int kNumMaxROIs = 4;
+    DRMRect crtc_rects[kNumMaxROIs] = {{0, 0, mixer_attributes_.width, mixer_attributes_.height}};
+    DRMRect conn_rects[kNumMaxROIs] = {{0, 0, display_attributes_.x_pixels,
+                                        display_attributes_.y_pixels}};
+
+    for (uint32_t i = 0; i < hw_layer_info.left_frame_roi.size(); i++) {
+      auto &roi = hw_layer_info.left_frame_roi.at(i);
+      // TODO(user): In multi PU, stitch ROIs vertically adjacent and upate plane destination
+      crtc_rects[i].left = UINT32(roi.left);
+      crtc_rects[i].right = UINT32(roi.right);
+      crtc_rects[i].top = UINT32(roi.top);
+      crtc_rects[i].bottom = UINT32(roi.bottom);
+      // TODO(user): In Dest scaler + PU, populate from HWDestScaleInfo->panel_roi
+      conn_rects[i].left = UINT32(roi.left);
+      conn_rects[i].right = UINT32(roi.right);
+      conn_rects[i].top = UINT32(roi.top);
+      conn_rects[i].bottom = UINT32(roi.bottom);
+    }
+
+    uint32_t num_rects = std::max(1u, static_cast<uint32_t>(hw_layer_info.left_frame_roi.size()));
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ROI, token_.crtc_id,
+                              num_rects, crtc_rects);
+    drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_ROI, token_.conn_id,
+                              num_rects, conn_rects);
+  }
+
+  for (uint32_t i = 0; i < hw_layer_count; i++) {
+    Layer &layer = hw_layer_info.hw_layers.at(i);
+    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 needs_rotation = false;
+
+    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;
+        needs_rotation = true;
+      }
+
+      uint32_t fb_id = registry_.GetFbId(input_buffer->planes[0].fd);
+      if (pipe_info->valid && fb_id) {
+        uint32_t pipe_id = pipe_info->pipe_id;
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ALPHA, pipe_id, layer.plane_alpha);
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ZORDER, pipe_id, pipe_info->z_order);
+        DRMBlendType blending = {};
+        SetBlending(layer.blending, &blending);
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_BLEND_TYPE, pipe_id, blending);
+        DRMRect src = {};
+        SetRect(pipe_info->src_roi, &src);
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SRC_RECT, pipe_id, src);
+        DRMRect dst = {};
+        SetRect(pipe_info->dst_roi, &dst);
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_DST_RECT, pipe_id, dst);
+
+        uint32_t rot_bit_mask = 0;
+        // In case of rotation, rotator handles flips
+        if (!needs_rotation) {
+          if (layer.transform.flip_horizontal) {
+            rot_bit_mask |= UINT32(DRMRotation::FLIP_H);
+          }
+          if (layer.transform.flip_vertical) {
+            rot_bit_mask |= UINT32(DRMRotation::FLIP_V);
+          }
+        }
+
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION, pipe_id, rot_bit_mask);
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_H_DECIMATION, pipe_id,
+                                  pipe_info->horizontal_decimation);
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_V_DECIMATION, pipe_id,
+                                  pipe_info->vertical_decimation);
+        uint32_t config = 0;
+        SetSrcConfig(layer.input_buffer, &config);
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SRC_CONFIG, pipe_id, config);;
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_FB_ID, pipe_id, fb_id);
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_CRTC, pipe_id, token_.crtc_id);
+        if (!validate && input_buffer->acquire_fence_fd >= 0) {
+          drm_atomic_intf_->Perform(DRMOps::PLANE_SET_INPUT_FENCE, pipe_id,
+                                    input_buffer->acquire_fence_fd);
+        }
+        if (hw_scale_) {
+          SDEScaler scaler_output = {};
+          hw_scale_->SetPlaneScaler(pipe_info->scale_data, &scaler_output);
+          // TODO(user): Remove qseed3 and add version check, then send appropriate scaler object
+          if (hw_resource_.has_qseed3) {
+            drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SCALER_CONFIG, pipe_id,
+                                      reinterpret_cast<uint64_t>(&scaler_output.scaler_v2));
+          }
+        }
+      }
+    }
+
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_CLK, token_.crtc_id, hw_layers->clock_hz);
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_AB, token_.crtc_id, hw_layers->ab_bps);
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_IB, token_.crtc_id, hw_layers->ib_bps);
+
+    DLOGI_IF(kTagDriverConfig, "System: clock=%d Hz, ab=%llu Bps ib=%llu Bps", hw_layers->clock_hz,
+             hw_layers->ab_bps, hw_layers->ib_bps);
+  }
+}
+
+DisplayError HWDeviceDRM::Validate(HWLayers *hw_layers) {
+  DTRACE_SCOPED();
+
+  registry_.RegisterCurrent(hw_layers);
+  SetupAtomic(hw_layers, true /* validate */);
+
+  int ret = drm_atomic_intf_->Validate();
+  if (ret) {
+    DLOGE("%s failed with error %d", __FUNCTION__, ret);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::Commit(HWLayers *hw_layers) {
+  DTRACE_SCOPED();
+
+  DisplayError err = kErrorNone;
+  registry_.RegisterCurrent(hw_layers);
+
+  if (default_mode_) {
+    err = DefaultCommit(hw_layers);
+  } else {
+    err = AtomicCommit(hw_layers);
+  }
+
+  registry_.UnregisterNext();
+
+  return err;
+}
+
+DisplayError HWDeviceDRM::DefaultCommit(HWLayers *hw_layers) {
+  DTRACE_SCOPED();
+
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  LayerStack *stack = hw_layer_info.stack;
+
+  stack->retire_fence_fd = -1;
+  for (Layer &layer : hw_layer_info.hw_layers) {
+    layer.input_buffer.release_fence_fd = -1;
+  }
+
+  DRMMaster *master = nullptr;
+  int ret = DRMMaster::GetInstance(&master);
+  if (ret < 0) {
+    DLOGE("Failed to acquire DRMMaster instance");
+    return kErrorResources;
+  }
+
+  DRMResMgr *res_mgr = nullptr;
+  ret = DRMResMgr::GetInstance(&res_mgr);
+  if (ret < 0) {
+    DLOGE("Failed to acquire DRMResMgr instance");
+    return kErrorResources;
+  }
+
+  int dev_fd = -1;
+  master->GetHandle(&dev_fd);
+
+  uint32_t connector_id = 0;
+  res_mgr->GetConnectorId(&connector_id);
+
+  uint32_t crtc_id = 0;
+  res_mgr->GetCrtcId(&crtc_id);
+
+  drmModeModeInfo mode;
+  res_mgr->GetMode(&mode);
+
+  uint32_t fb_id = registry_.GetFbId(hw_layer_info.hw_layers.at(0).input_buffer.planes[0].fd);
+  ret = drmModeSetCrtc(dev_fd, crtc_id, fb_id, 0 /* x */, 0 /* y */, &connector_id,
+                       1 /* num_connectors */, &mode);
+  if (ret < 0) {
+    DLOGE("drmModeSetCrtc failed dev fd %d, fb_id %d, crtc id %d, connector id %d, %s", dev_fd,
+          fb_id, crtc_id, connector_id, strerror(errno));
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::AtomicCommit(HWLayers *hw_layers) {
+  DTRACE_SCOPED();
+  SetupAtomic(hw_layers, false /* validate */);
+
+  int ret = drm_atomic_intf_->Commit(false /* synchronous */);
+  if (ret) {
+    DLOGE("%s failed with error %d crtc %d", __FUNCTION__, ret, token_.crtc_id);
+    return kErrorHardware;
+  }
+
+  int release_fence = -1;
+  int retire_fence = -1;
+
+  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence);
+  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE, token_.conn_id, &retire_fence);
+
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  LayerStack *stack = hw_layer_info.stack;
+  stack->retire_fence_fd = retire_fence;
+
+  for (uint32_t i = 0; i < hw_layer_info.hw_layers.size(); i++) {
+    Layer &layer = hw_layer_info.hw_layers.at(i);
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+    if (hw_rotator_session->hw_block_count) {
+      hw_rotator_session->output_buffer.release_fence_fd = Sys::dup_(release_fence);
+    } else {
+      layer.input_buffer.release_fence_fd = Sys::dup_(release_fence);
+    }
+  }
+
+  hw_layer_info.sync_handle = release_fence;
+
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::Flush() {
+  return kErrorNone;
+}
+
+void HWDeviceDRM::SetBlending(const LayerBlending &source, DRMBlendType *target) {
+  switch (source) {
+    case kBlendingPremultiplied:
+      *target = DRMBlendType::PREMULTIPLIED;
+      break;
+    case kBlendingOpaque:
+      *target = DRMBlendType::OPAQUE;
+      break;
+    case kBlendingCoverage:
+      *target = DRMBlendType::COVERAGE;
+      break;
+    default:
+      *target = DRMBlendType::UNDEFINED;
+  }
+}
+
+
+void HWDeviceDRM::SetSrcConfig(const LayerBuffer &input_buffer, uint32_t *config) {
+  if (input_buffer.flags.interlace) {
+    *config |= (0x01 << UINT32(DRMSrcConfig::DEINTERLACE));
+  }
+}
+
+void HWDeviceDRM::SetRect(const LayerRect &source, DRMRect *target) {
+  target->left = UINT32(source.left);
+  target->top = UINT32(source.top);
+  target->right = UINT32(source.right);
+  target->bottom = UINT32(source.bottom);
+}
+
+bool HWDeviceDRM::EnableHotPlugDetection(int enable) {
+  return true;
+}
+
+void HWDeviceDRM::ResetDisplayParams() {}
+
+DisplayError HWDeviceDRM::SetCursorPosition(HWLayers *hw_layers, int x, int y) {
+  DTRACE_SCOPED();
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::GetPPFeaturesVersion(PPFeatureVersion *vers) {
+  struct DRMPPFeatureInfo info = {};
+  for (uint32_t i = 0; i < kMaxNumPPFeatures; i++) {
+    memset(&info, 0, sizeof(struct DRMPPFeatureInfo));
+    info.id = HWColorManagerDrm::ToDrmFeatureId(i);
+    if (info.id >= sde_drm::kPPFeaturesMax)
+      continue;
+    // use crtc_id_ = 0 since PP features are same across all CRTCs
+    drm_mgr_intf_->GetCrtcPPInfo(0, info);
+    vers->version[i] = HWColorManagerDrm::GetFeatureVersion(info);
+  }
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::SetPPFeatures(PPFeaturesConfig *feature_list) {
+  int ret = 0;
+  PPFeatureInfo *feature = NULL;
+  DRMPPFeatureInfo kernel_params = {};
+
+  while (true) {
+    ret = feature_list->RetrieveNextFeature(&feature);
+    if (ret)
+      break;
+
+    if (feature) {
+      DLOGV_IF(kTagDriverConfig, "feature_id = %d", feature->feature_id_);
+      if (!HWColorManagerDrm::GetDrmFeature[feature->feature_id_]) {
+        DLOGE("GetDrmFeature is not valid for feature %d", feature->feature_id_);
+        continue;
+      }
+      ret = HWColorManagerDrm::GetDrmFeature[feature->feature_id_](*feature, &kernel_params);
+      if (!ret)
+        drm_atomic_intf_->Perform(DRMOps::CRTC_SET_POST_PROC, token_.crtc_id, &kernel_params);
+      HWColorManagerDrm::FreeDrmFeatureData(&kernel_params);
+    }
+  }
+
+  // Once all features were consumed, then destroy all feature instance from feature_list,
+  feature_list->Reset();
+
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::SetVSyncState(bool enable) {
+  return kErrorNotSupported;
+}
+
+void HWDeviceDRM::SetIdleTimeoutMs(uint32_t timeout_ms) {}
+
+DisplayError HWDeviceDRM::SetDisplayMode(const HWDisplayMode hw_display_mode) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::SetRefreshRate(uint32_t refresh_rate) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::SetPanelBrightness(int level) {
+  DisplayError err = kErrorNone;
+  char buffer[kMaxSysfsCommandLength] = {0};
+
+  DLOGV_IF(kTagDriverConfig, "Set brightness level to %d", level);
+  int fd = Sys::open_(kBrightnessNode, O_RDWR);
+  if (fd < 0) {
+    DLOGV_IF(kTagDriverConfig, "Failed to open node = %s, error = %s ", kBrightnessNode,
+             strerror(errno));
+    return kErrorFileDescriptor;
+  }
+
+  int32_t bytes = snprintf(buffer, kMaxSysfsCommandLength, "%d\n", level);
+  ssize_t ret = Sys::pwrite_(fd, buffer, static_cast<size_t>(bytes), 0);
+  if (ret <= 0) {
+    DLOGV_IF(kTagDriverConfig, "Failed to write to node = %s, error = %s ", kBrightnessNode,
+             strerror(errno));
+    err = kErrorHardware;
+  }
+
+  Sys::close_(fd);
+
+  return err;
+}
+
+DisplayError HWDeviceDRM::GetPanelBrightness(int *level) {
+  DisplayError err = kErrorNone;
+  char brightness[kMaxStringLength] = {0};
+
+  if (!level) {
+    DLOGV_IF(kTagDriverConfig, "Invalid input, null pointer.");
+    return kErrorParameters;
+  }
+
+  int fd = Sys::open_(kBrightnessNode, O_RDWR);
+  if (fd < 0) {
+    DLOGV_IF(kTagDriverConfig, "Failed to open brightness node = %s, error = %s", kBrightnessNode,
+             strerror(errno));
+    return kErrorFileDescriptor;
+  }
+
+  if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
+    *level = atoi(brightness);
+    DLOGV_IF(kTagDriverConfig, "Brightness level = %d", *level);
+  } else {
+    DLOGV_IF(kTagDriverConfig, "Failed to read panel brightness");
+    err = kErrorHardware;
+  }
+
+  Sys::close_(fd);
+
+  return err;
+}
+
+DisplayError HWDeviceDRM::CachePanelBrightness(int level) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::GetHWScanInfo(HWScanInfo *scan_info) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::GetVideoFormat(uint32_t config_index, uint32_t *video_format) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::GetMaxCEAFormat(uint32_t *max_cea_format) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::SetS3DMode(HWS3DMode s3d_mode) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDeviceDRM::SetScaleLutConfig(HWScaleLutInfo *lut_info) {
+  sde_drm::DRMScalerLUTInfo drm_lut_info = {};
+  drm_lut_info.cir_lut = lut_info->cir_lut;
+  drm_lut_info.dir_lut = lut_info->dir_lut;
+  drm_lut_info.sep_lut = lut_info->sep_lut;
+  drm_lut_info.cir_lut_size = lut_info->cir_lut_size;
+  drm_lut_info.dir_lut_size = lut_info->dir_lut_size;
+  drm_lut_info.sep_lut_size = lut_info->sep_lut_size;
+  drm_mgr_intf_->SetScalerLUT(drm_lut_info);
+
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+  if (!hw_resource_.hw_dest_scalar_info.count) {
+    return kErrorNotSupported;
+  }
+
+  if (mixer_attributes.width > display_attributes_.x_pixels ||
+      mixer_attributes.height > display_attributes_.y_pixels) {
+    DLOGW("Input resolution exceeds display resolution! input: res %dx%d display: res %dx%d",
+          mixer_attributes.width, mixer_attributes.height, display_attributes_.x_pixels,
+          display_attributes_.y_pixels);
+    return kErrorNotSupported;
+  }
+
+  uint32_t max_input_width = hw_resource_.hw_dest_scalar_info.max_input_width;
+  if (display_attributes_.is_device_split) {
+    max_input_width *= 2;
+  }
+
+  if (mixer_attributes.width > max_input_width) {
+    DLOGW("Input width exceeds width limit! input_width %d width_limit %d", mixer_attributes.width,
+          max_input_width);
+    return kErrorNotSupported;
+  }
+
+  float mixer_aspect_ratio = FLOAT(mixer_attributes.width) / FLOAT(mixer_attributes.height);
+  float display_aspect_ratio =
+      FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels);
+
+  if (display_aspect_ratio != mixer_aspect_ratio) {
+    DLOGW("Aspect ratio mismatch! input: res %dx%d display: res %dx%d", mixer_attributes.width,
+          mixer_attributes.height, display_attributes_.x_pixels, display_attributes_.y_pixels);
+    return kErrorNotSupported;
+  }
+
+  float scale_x = FLOAT(display_attributes_.x_pixels) / FLOAT(mixer_attributes.width);
+  float scale_y = FLOAT(display_attributes_.y_pixels) / FLOAT(mixer_attributes.height);
+  float max_scale_up = hw_resource_.hw_dest_scalar_info.max_scale_up;
+  if (scale_x > max_scale_up || scale_y > max_scale_up) {
+    DLOGW(
+        "Up scaling ratio exceeds for destination scalar upscale limit scale_x %f scale_y %f "
+        "max_scale_up %f",
+        scale_x, scale_y, max_scale_up);
+    return kErrorNotSupported;
+  }
+
+  float mixer_split_ratio = FLOAT(mixer_attributes_.split_left) / FLOAT(mixer_attributes_.width);
+
+  mixer_attributes_ = mixer_attributes;
+  mixer_attributes_.split_left = mixer_attributes_.width;
+  if (display_attributes_.is_device_split) {
+    mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWDeviceDRM::GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
+  if (!mixer_attributes) {
+    return kErrorParameters;
+  }
+
+  mixer_attributes_.width = display_attributes_.x_pixels;
+  mixer_attributes_.height = display_attributes_.y_pixels;
+  mixer_attributes_.split_left = display_attributes_.is_device_split
+                                     ? hw_panel_info_.split_info.left_split
+                                     : mixer_attributes_.width;
+  *mixer_attributes = mixer_attributes_;
+
+  return kErrorNone;
+}
+
+void HWDeviceDRM::UpdateMixerAttributes() {
+  mixer_attributes_.width = display_attributes_.x_pixels;
+  mixer_attributes_.height = display_attributes_.y_pixels;
+  mixer_attributes_.split_left = display_attributes_.is_device_split
+                                     ? hw_panel_info_.split_info.left_split
+                                     : mixer_attributes_.width;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/drm/hw_device_drm.h b/sdm845/sdm/libs/core/drm/hw_device_drm.h
new file mode 100644
index 0000000..ad7a3e3
--- /dev/null
+++ b/sdm845/sdm/libs/core/drm/hw_device_drm.h
@@ -0,0 +1,177 @@
+/*
+* Copyright (c) 2017, 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_DRM_H__
+#define __HW_DEVICE_DRM_H__
+
+#include <drm_interface.h>
+#include <errno.h>
+#include <pthread.h>
+#include <xf86drmMode.h>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "hw_interface.h"
+#include "hw_scale_drm.h"
+
+#define IOCTL_LOGE(ioctl, type) \
+  DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, type, errno, strerror(errno))
+
+namespace sdm {
+class HWInfoInterface;
+
+class HWDeviceDRM : public HWInterface {
+ public:
+  HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+                       HWInfoInterface *hw_info_intf);
+  virtual ~HWDeviceDRM() {}
+  virtual DisplayError Init();
+  virtual DisplayError Deinit();
+
+ protected:
+  // From HWInterface
+  virtual DisplayError GetActiveConfig(uint32_t *active_config);
+  virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+  virtual DisplayError GetDisplayAttributes(uint32_t index,
+                                            HWDisplayAttributes *display_attributes);
+  virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
+  virtual DisplayError SetDisplayAttributes(uint32_t index);
+  virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
+  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 DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
+  virtual DisplayError SetPPFeatures(PPFeaturesConfig *feature_list);
+  // This API is no longer supported, expectation is to call the correct API on HWEvents
+  virtual DisplayError SetVSyncState(bool enable);
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+  virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+  virtual DisplayError SetPanelBrightness(int level);
+  virtual DisplayError CachePanelBrightness(int level);
+  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 SetCursorPosition(HWLayers *hw_layers, int x, int y);
+  virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
+  virtual DisplayError GetPanelBrightness(int *level);
+  virtual DisplayError SetAutoRefresh(bool enable) { return kErrorNone; }
+  virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
+  virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
+  virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
+  virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
+  virtual void InitializeConfigs();
+
+  enum {
+    kHWEventVSync,
+    kHWEventBlank,
+  };
+
+  static const int kMaxStringLength = 1024;
+  static const int kNumPhysicalDisplays = 2;
+  static const int kMaxSysfsCommandLength = 12;
+  static constexpr const char *kBrightnessNode =
+    "/sys/class/backlight/panel0-backlight/brightness";
+
+  DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
+  DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format, uint32_t width,
+                         uint32_t *target);
+  DisplayError PopulateDisplayAttributes();
+  void PopulateHWPanelInfo();
+  void GetHWDisplayPortAndMode();
+  void GetHWPanelMaxBrightness();
+  void ResetDisplayParams();
+  bool EnableHotPlugDetection(int enable);
+  void UpdateMixerAttributes();
+  void SetBlending(const LayerBlending &source, sde_drm::DRMBlendType *target);
+  void SetSrcConfig(const LayerBuffer &input_buffer, uint32_t *config);
+  void SetRect(const LayerRect &source, sde_drm::DRMRect *target);
+  DisplayError DefaultCommit(HWLayers *hw_layers);
+  DisplayError AtomicCommit(HWLayers *hw_layers);
+  void SetupAtomic(HWLayers *hw_layers, bool validate);
+
+  class Registry {
+   public:
+    explicit Registry(BufferAllocator *buffer_allocator) : buffer_allocator_(buffer_allocator) {}
+    // Call on each validate and commit to register layer buffers
+    void RegisterCurrent(HWLayers *hw_layers);
+    // Call at the end of draw cycle to clear the next slot for business
+    void UnregisterNext();
+    // Call on display disconnect to release all gem handles and fb_ids
+    void Clear();
+    // Maps given fd to FB ID
+    void MapBufferToFbId(LayerBuffer* buffer);
+    // Finds an fb_id corresponding to an fd in current map
+    uint32_t GetFbId(int fd);
+
+   private:
+    static const int kCycleDelay = 3;  // N cycle delay before destroy
+    // fd to fb_id map. fd is used as key only for a single draw cycle between
+    // prepare and commit. It should not be used for caching in future due to fd recycling
+    std::unordered_map<int, uint32_t> hashmap_[kCycleDelay] {};
+    int current_index_ = 0;
+    BufferAllocator *buffer_allocator_ = {};
+  };
+
+ protected:
+  const char *device_name_ = {};
+  bool deferred_initialize_ = false;
+  sde_drm::DRMDisplayType disp_type_ = {};
+  HWInfoInterface *hw_info_intf_ = {};
+  BufferSyncHandler *buffer_sync_handler_ = {};
+  int dev_fd_ = -1;
+  Registry registry_;
+  sde_drm::DRMDisplayToken token_ = {};
+  HWResourceInfo hw_resource_ = {};
+  HWPanelInfo hw_panel_info_ = {};
+  HWDeviceType device_type_ = {};
+  sde_drm::DRMManagerInterface *drm_mgr_intf_ = {};
+  sde_drm::DRMAtomicReqInterface *drm_atomic_intf_ = {};
+  sde_drm::DRMConnectorInfo connector_info_ = {};
+  drmModeModeInfo current_mode_ = {};
+  HWDisplayAttributes display_attributes_ = {};
+
+ private:
+  bool synchronous_commit_ = false;
+  HWMixerAttributes mixer_attributes_ = {};
+  bool default_mode_ = false;
+  std::string interface_str_ = "DSI";
+  HWScaleDRM *hw_scale_ = {};
+};
+
+}  // namespace sdm
+
+#endif  // __HW_DEVICE_DRM_H__
diff --git a/sdm845/sdm/libs/core/drm/hw_events_drm.cpp b/sdm845/sdm/libs/core/drm/hw_events_drm.cpp
new file mode 100644
index 0000000..cea76fc
--- /dev/null
+++ b/sdm845/sdm/libs/core/drm/hw_events_drm.cpp
@@ -0,0 +1,327 @@
+/*
+* Copyright (c) 2017, 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 <drm_master.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <utils/debug.h>
+#include <utils/sys.h>
+#include <xf86drm.h>
+
+#include <algorithm>
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "hw_events_drm.h"
+
+#define __CLASS__ "HWEventsDRM"
+
+namespace sdm {
+
+using drm_utils::DRMMaster;
+
+DisplayError HWEventsDRM::InitializePollFd() {
+  for (uint32_t i = 0; i < event_data_list_.size(); i++) {
+    char data[kMaxStringLength]{};
+    HWEventData &event_data = event_data_list_[i];
+    poll_fds_[i].fd = -1;
+
+    switch (event_data.event_type) {
+      case HWEvent::VSYNC: {
+        poll_fds_[i].events = POLLIN | POLLPRI | POLLERR;
+        DRMMaster *master = nullptr;
+        int ret = DRMMaster::GetInstance(&master);
+        if (ret < 0) {
+          DLOGE("Failed to acquire DRMMaster instance");
+          return kErrorNotSupported;
+        }
+        master->GetHandle(&poll_fds_[i].fd);
+        vsync_index_ = i;
+      } break;
+      case HWEvent::EXIT: {
+        // Create an eventfd to be used to unblock the poll system call when
+        // a thread is exiting.
+        poll_fds_[i].fd = Sys::eventfd_(0, 0);
+        poll_fds_[i].events |= POLLIN;
+        // Clear any existing data
+        Sys::pread_(poll_fds_[i].fd, data, kMaxStringLength, 0);
+      } break;
+      case HWEvent::IDLE_NOTIFY:
+      case HWEvent::CEC_READ_MESSAGE:
+      case HWEvent::SHOW_BLANK_EVENT:
+      case HWEvent::THERMAL_LEVEL:
+      case HWEvent::IDLE_POWER_COLLAPSE:
+        break;
+    }
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWEventsDRM::SetEventParser() {
+  DisplayError error = kErrorNone;
+
+  for (auto &event_data : event_data_list_) {
+    switch (event_data.event_type) {
+      case HWEvent::VSYNC:
+        event_data.event_parser = &HWEventsDRM::HandleVSync;
+        break;
+      case HWEvent::IDLE_NOTIFY:
+        event_data.event_parser = &HWEventsDRM::HandleIdleTimeout;
+        break;
+      case HWEvent::CEC_READ_MESSAGE:
+        event_data.event_parser = &HWEventsDRM::HandleCECMessage;
+        break;
+      case HWEvent::EXIT:
+        event_data.event_parser = &HWEventsDRM::HandleThreadExit;
+        break;
+      case HWEvent::SHOW_BLANK_EVENT:
+        event_data.event_parser = &HWEventsDRM::HandleBlank;
+        break;
+      case HWEvent::THERMAL_LEVEL:
+        event_data.event_parser = &HWEventsDRM::HandleThermal;
+        break;
+      case HWEvent::IDLE_POWER_COLLAPSE:
+        event_data.event_parser = &HWEventsDRM::HandleIdlePowerCollapse;
+        break;
+      default:
+        error = kErrorParameters;
+        break;
+    }
+  }
+
+  return error;
+}
+
+void HWEventsDRM::PopulateHWEventData(const vector<HWEvent> &event_list) {
+  for (auto &event : event_list) {
+    HWEventData event_data;
+    event_data.event_type = event;
+    event_data_list_.push_back(std::move(event_data));
+  }
+
+  SetEventParser();
+  InitializePollFd();
+}
+
+DisplayError HWEventsDRM::Init(int display_type, HWEventHandler *event_handler,
+                               const vector<HWEvent> &event_list) {
+  if (!event_handler)
+    return kErrorParameters;
+
+  event_handler_ = event_handler;
+  poll_fds_.resize(event_list.size());
+  event_thread_name_ += " - " + std::to_string(display_type);
+
+  PopulateHWEventData(event_list);
+
+  if (pthread_create(&event_thread_, NULL, &DisplayEventThread, this) < 0) {
+    DLOGE("Failed to start %s, error = %s", event_thread_name_.c_str());
+    return kErrorResources;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWEventsDRM::Deinit() {
+  exit_threads_ = true;
+  Sys::pthread_cancel_(event_thread_);
+  WakeUpEventThread();
+  pthread_join(event_thread_, NULL);
+  CloseFds();
+
+  return kErrorNone;
+}
+
+DisplayError HWEventsDRM::SetEventState(HWEvent event, bool enable, void *arg) {
+  switch (event) {
+    case HWEvent::VSYNC:
+      vsync_enabled_ = enable;
+      if (enable) {
+        WakeUpEventThread();
+      }
+      break;
+    default:
+      DLOGE("Event not supported");
+      return kErrorNotSupported;
+  }
+
+  return kErrorNone;
+}
+
+void HWEventsDRM::WakeUpEventThread() {
+  for (uint32_t i = 0; i < event_data_list_.size(); i++) {
+    if (event_data_list_[i].event_type == HWEvent::EXIT) {
+      uint64_t exit_value = 1;
+      ssize_t write_size = Sys::write_(poll_fds_[i].fd, &exit_value, sizeof(uint64_t));
+      if (write_size != sizeof(uint64_t)) {
+        DLOGW("Error triggering exit fd (%d). write size = %d, error = %s", poll_fds_[i].fd,
+              write_size, strerror(errno));
+      }
+      break;
+    }
+  }
+}
+
+DisplayError HWEventsDRM::CloseFds() {
+  for (uint32_t i = 0; i < event_data_list_.size(); i++) {
+    switch (event_data_list_[i].event_type) {
+      case HWEvent::VSYNC:
+        poll_fds_[i].fd = -1;
+        break;
+      case HWEvent::EXIT:
+        Sys::close_(poll_fds_[i].fd);
+        poll_fds_[i].fd = -1;
+        break;
+      case HWEvent::IDLE_NOTIFY:
+      case HWEvent::CEC_READ_MESSAGE:
+      case HWEvent::SHOW_BLANK_EVENT:
+      case HWEvent::THERMAL_LEVEL:
+      case HWEvent::IDLE_POWER_COLLAPSE:
+        break;
+      default:
+        return kErrorNotSupported;
+    }
+  }
+
+  return kErrorNone;
+}
+
+void *HWEventsDRM::DisplayEventThread(void *context) {
+  if (context) {
+    return reinterpret_cast<HWEventsDRM *>(context)->DisplayEventHandler();
+  }
+
+  return NULL;
+}
+
+void *HWEventsDRM::DisplayEventHandler() {
+  char data[kMaxStringLength]{};
+
+  prctl(PR_SET_NAME, event_thread_name_.c_str(), 0, 0, 0);
+  setpriority(PRIO_PROCESS, 0, kThreadPriorityUrgent);
+
+  while (!exit_threads_) {
+    if (vsync_enabled_ && RegisterVSync() != kErrorNone) {
+      pthread_exit(0);
+      return nullptr;
+    }
+
+    int error = Sys::poll_(poll_fds_.data(), UINT32(poll_fds_.size()), -1);
+    if (error <= 0) {
+      DLOGW("poll failed. error = %s", strerror(errno));
+      continue;
+    }
+
+    for (uint32_t i = 0; i < event_data_list_.size(); i++) {
+      pollfd &poll_fd = poll_fds_[i];
+      switch (event_data_list_[i].event_type) {
+        case HWEvent::VSYNC:
+          (this->*(event_data_list_[i]).event_parser)(nullptr);
+          break;
+        case HWEvent::EXIT:
+          if ((poll_fd.revents & POLLIN) &&
+              (Sys::read_(poll_fd.fd, data, kMaxStringLength) > 0)) {
+            (this->*(event_data_list_[i]).event_parser)(data);
+          }
+          break;
+        case HWEvent::IDLE_NOTIFY:
+        case HWEvent::CEC_READ_MESSAGE:
+        case HWEvent::SHOW_BLANK_EVENT:
+        case HWEvent::THERMAL_LEVEL:
+        case HWEvent::IDLE_POWER_COLLAPSE:
+          if (poll_fd.fd >= 0 && (poll_fd.revents & POLLPRI) &&
+              (Sys::pread_(poll_fd.fd, data, kMaxStringLength, 0) > 0)) {
+            (this->*(event_data_list_[i]).event_parser)(data);
+          }
+          break;
+      }
+    }
+  }
+
+  pthread_exit(0);
+
+  return nullptr;
+}
+
+DisplayError HWEventsDRM::RegisterVSync() {
+  drmVBlank vblank{};
+  vblank.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT);
+  vblank.request.sequence = 1;
+  // DRM hack to pass in context to unused field signal. Driver will write this to the node being
+  // polled on, and will be read as part of drm event handling and sent to handler
+  vblank.request.signal = reinterpret_cast<unsigned long>(this);  // NOLINT
+  int error = drmWaitVBlank(poll_fds_[vsync_index_].fd, &vblank);
+  if (error < 0) {
+    DLOGE("drmWaitVBlank failed with err %d", errno);
+    return kErrorResources;
+  }
+
+  return kErrorNone;
+}
+
+void HWEventsDRM::HandleVSync(char *data) {
+  if (poll_fds_[vsync_index_].revents & (POLLIN | POLLPRI)) {
+    drmEventContext event = {};
+    event.version = DRM_EVENT_CONTEXT_VERSION;
+    event.vblank_handler = &HWEventsDRM::VSyncHandlerCallback;
+    int error = drmHandleEvent(poll_fds_[vsync_index_].fd, &event);
+    if (error != 0) {
+      DLOGE("drmHandleEvent failed: %i", error);
+    }
+  }
+}
+
+void HWEventsDRM::VSyncHandlerCallback(int fd, unsigned int sequence, unsigned int tv_sec,
+                                       unsigned int tv_usec, void *data) {
+  int64_t timestamp = (int64_t)(tv_sec)*1000000000 + (int64_t)(tv_usec)*1000;
+  reinterpret_cast<HWEventsDRM *>(data)->event_handler_->VSync(timestamp);
+}
+
+void HWEventsDRM::HandleIdleTimeout(char *data) {
+  event_handler_->IdleTimeout();
+}
+
+void HWEventsDRM::HandleCECMessage(char *data) {
+  event_handler_->CECMessage(data);
+}
+
+void HWEventsDRM::HandleIdlePowerCollapse(char *data) {
+  event_handler_->IdlePowerCollapse();
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/drm/hw_events_drm.h b/sdm845/sdm/libs/core/drm/hw_events_drm.h
new file mode 100644
index 0000000..41050c7
--- /dev/null
+++ b/sdm845/sdm/libs/core/drm/hw_events_drm.h
@@ -0,0 +1,94 @@
+/*
+* Copyright (c) 2017, 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_EVENTS_DRM_H__
+#define __HW_EVENTS_DRM_H__
+
+#include <sys/poll.h>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "hw_events_interface.h"
+#include "hw_interface.h"
+
+namespace sdm {
+
+using std::vector;
+
+class HWEventsDRM : public HWEventsInterface {
+ public:
+  virtual DisplayError Init(int display_type, HWEventHandler *event_handler,
+                            const vector<HWEvent> &event_list);
+  virtual DisplayError Deinit();
+  virtual DisplayError SetEventState(HWEvent event, bool enable, void *aux = nullptr);
+
+ private:
+  static const int kMaxStringLength = 1024;
+
+  typedef void (HWEventsDRM::*EventParser)(char *);
+
+  struct HWEventData {
+    HWEvent event_type {};
+    EventParser event_parser {};
+  };
+
+  static void *DisplayEventThread(void *context);
+  static void VSyncHandlerCallback(int fd, unsigned int sequence, unsigned int tv_sec,
+                                   unsigned int tv_usec, void *data);
+
+  void *DisplayEventHandler();
+  void HandleVSync(char *data);
+  void HandleIdleTimeout(char *data);
+  void HandleCECMessage(char *data);
+  void HandleThreadExit(char *data) {}
+  void HandleThermal(char *data) {}
+  void HandleBlank(char *data) {}
+  void HandleIdlePowerCollapse(char *data);
+  void PopulateHWEventData(const vector<HWEvent> &event_list);
+  void WakeUpEventThread();
+  DisplayError SetEventParser();
+  DisplayError InitializePollFd();
+  DisplayError CloseFds();
+  DisplayError RegisterVSync();
+
+  HWEventHandler *event_handler_{};
+  vector<HWEventData> event_data_list_{};
+  vector<pollfd> poll_fds_{};
+  pthread_t event_thread_{};
+  std::string event_thread_name_ = "SDM_EventThread";
+  bool exit_threads_ = false;
+  uint32_t vsync_index_ = 0;
+  bool vsync_enabled_ = true;
+};
+
+}  // namespace sdm
+
+#endif  // __HW_EVENTS_DRM_H__
diff --git a/sdm845/sdm/libs/core/drm/hw_info_drm.cpp b/sdm845/sdm/libs/core/drm/hw_info_drm.cpp
new file mode 100644
index 0000000..6258d73
--- /dev/null
+++ b/sdm845/sdm/libs/core/drm/hw_info_drm.cpp
@@ -0,0 +1,610 @@
+/*
+* Copyright (c) 2017, 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 <drm/drm_fourcc.h>
+#include <drm_lib_loader.h>
+#include <drm_master.h>
+#include <drm_res_mgr.h>
+#include <fcntl.h>
+#include <media/msm_sde_rotator.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/sys.h>
+
+#include <algorithm>
+#include <fstream>
+#include <iostream>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "hw_info_drm.h"
+
+#ifndef DRM_FORMAT_MOD_QCOM_COMPRESSED
+#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
+#endif
+#ifndef DRM_FORMAT_MOD_QCOM_DX
+#define DRM_FORMAT_MOD_QCOM_DX fourcc_mod_code(QCOM, 0x2)
+#endif
+#ifndef DRM_FORMAT_MOD_QCOM_TIGHT
+#define DRM_FORMAT_MOD_QCOM_TIGHT fourcc_mod_code(QCOM, 0x4)
+#endif
+
+#define __CLASS__ "HWInfoDRM"
+
+using drm_utils::DRMMaster;
+using drm_utils::DRMResMgr;
+using drm_utils::DRMLogger;
+using drm_utils::DRMLibLoader;
+using sde_drm::GetDRMManager;
+using sde_drm::DRMPlanesInfo;
+using sde_drm::DRMCrtcInfo;
+using sde_drm::DRMPlaneType;
+
+using std::vector;
+using std::map;
+using std::string;
+using std::fstream;
+using std::to_string;
+
+namespace sdm {
+
+class DRMLoggerImpl : public DRMLogger {
+ public:
+#define PRINTLOG(method, format, buf)        \
+  va_list list;                              \
+  va_start(list, format);                    \
+  vsnprintf(buf, sizeof(buf), format, list); \
+  va_end(list);                              \
+  Debug::Get()->method(kTagNone, "%s", buf);
+
+  void Error(const char *format, ...) { PRINTLOG(Error, format, buf_); }
+  void Warning(const char *format, ...) { PRINTLOG(Warning, format, buf_); }
+  void Info(const char *format, ...) { PRINTLOG(Info, format, buf_); }
+  void Debug(const char *format, ...) { PRINTLOG(Debug, format, buf_); }
+
+ private:
+  char buf_[1024] = {};
+};
+
+HWResourceInfo *HWInfoDRM::hw_resource_ = nullptr;
+
+HWInfoDRM::HWInfoDRM() {
+  DRMLogger::Set(new DRMLoggerImpl());
+  default_mode_ = (DRMLibLoader::GetInstance()->IsLoaded() == false);
+  if (!default_mode_) {
+    DRMMaster *drm_master = {};
+    int dev_fd = -1;
+    DRMMaster::GetInstance(&drm_master);
+    if (!drm_master) {
+      DLOGE("Failed to acquire DRMMaster instance");
+      return;
+    }
+    drm_master->GetHandle(&dev_fd);
+    DRMLibLoader::GetInstance()->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_);
+  }
+}
+
+HWInfoDRM::~HWInfoDRM() {
+  delete hw_resource_;
+  hw_resource_ = nullptr;
+
+  if (drm_mgr_intf_) {
+    DRMLibLoader::GetInstance()->FuncDestroyDRMManager()();
+    drm_mgr_intf_ = nullptr;
+  }
+
+  DRMLibLoader::Destroy();
+  DRMMaster::DestroyInstance();
+}
+
+DisplayError HWInfoDRM::GetDynamicBWLimits(HWResourceInfo *hw_resource) {
+  HWDynBwLimitInfo* bw_info = &hw_resource->dyn_bw_info;
+  for (int index = 0; index < kBwModeMax; index++) {
+    bw_info->total_bw_limit[index] = hw_resource->max_bandwidth_low;
+    bw_info->pipe_bw_limit[index] = hw_resource->max_pipe_bw;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWInfoDRM::GetHWResourceInfo(HWResourceInfo *hw_resource) {
+  if (hw_resource_) {
+    *hw_resource = *hw_resource_;
+    return kErrorNone;
+  }
+
+  hw_resource->num_blending_stages = 1;
+  hw_resource->max_pipe_width = 2560;
+  hw_resource->max_cursor_size = 128;
+  hw_resource->max_scale_down = 1;
+  hw_resource->max_scale_up = 1;
+  hw_resource->has_decimation = false;
+  hw_resource->max_bandwidth_low = 9600000;
+  hw_resource->max_bandwidth_high = 9600000;
+  hw_resource->max_pipe_bw = 4500000;
+  hw_resource->max_sde_clk = 412500000;
+  hw_resource->clk_fudge_factor = FLOAT(105) / FLOAT(100);
+  hw_resource->macrotile_nv12_factor = 8;
+  hw_resource->macrotile_factor = 4;
+  hw_resource->linear_factor = 1;
+  hw_resource->scale_factor = 1;
+  hw_resource->extra_fudge_factor = 2;
+  hw_resource->amortizable_threshold = 25;
+  hw_resource->system_overhead_lines = 0;
+  hw_resource->hw_dest_scalar_info.count = 0;
+  hw_resource->hw_dest_scalar_info.max_scale_up = 0;
+  hw_resource->hw_dest_scalar_info.max_input_width = 0;
+  hw_resource->hw_dest_scalar_info.max_output_width = 0;
+  hw_resource->is_src_split = true;
+  hw_resource->has_dyn_bw_support = false;
+  hw_resource->has_qseed3 = false;
+  hw_resource->has_concurrent_writeback = false;
+
+  // TODO(user): Deprecate
+  hw_resource->hw_version = kHWMdssVersion5;
+  hw_resource->hw_revision = 0;
+  hw_resource->max_mixer_width = 0;
+  hw_resource->writeback_index = 0;
+  hw_resource->has_bwc = false;
+  hw_resource->has_ubwc = true;
+  hw_resource->has_macrotile = true;
+  hw_resource->separate_rotator = true;
+  hw_resource->has_non_scalar_rgb = false;
+
+  GetSystemInfo(hw_resource);
+  GetHWPlanesInfo(hw_resource);
+  GetWBInfo(hw_resource);
+
+  // Disable destination scalar count to 0 if extension library is not present
+  DynLib extension_lib;
+  if (!extension_lib.Open("libsdmextension.so")) {
+    hw_resource->hw_dest_scalar_info.count = 0;
+  }
+
+  DLOGI("Max plane width = %d", hw_resource->max_pipe_width);
+  DLOGI("Max cursor width = %d", hw_resource->max_cursor_size);
+  DLOGI("Max plane upscale = %d", hw_resource->max_scale_up);
+  DLOGI("Max plane downscale = %d", hw_resource->max_scale_down);
+  DLOGI("Has Decimation = %d", hw_resource->has_decimation);
+  DLOGI("Max Blending Stages = %d", hw_resource->num_blending_stages);
+  DLOGI("Has Source Split = %d", hw_resource->is_src_split);
+  DLOGI("Has QSEED3 = %d", hw_resource->has_qseed3);
+  DLOGI("Has UBWC = %d", hw_resource->has_ubwc);
+  DLOGI("Has Concurrent Writeback = %d", hw_resource->has_concurrent_writeback);
+  DLOGI("Max Low Bw = %" PRIu64 "", hw_resource->max_bandwidth_low);
+  DLOGI("Max High Bw = % " PRIu64 "", hw_resource->max_bandwidth_high);
+  DLOGI("Max Pipe Bw = %" PRIu64 " KBps", hw_resource->max_pipe_bw);
+  DLOGI("MaxSDEClock = % " PRIu64 " Hz", hw_resource->max_sde_clk);
+  DLOGI("Clock Fudge Factor = %f", hw_resource->clk_fudge_factor);
+  DLOGI("Prefill factors:");
+  DLOGI("\tTiled_NV12 = %d", hw_resource->macrotile_nv12_factor);
+  DLOGI("\tTiled = %d", hw_resource->macrotile_factor);
+  DLOGI("\tLinear = %d", hw_resource->linear_factor);
+  DLOGI("\tScale = %d", hw_resource->scale_factor);
+  DLOGI("\tFudge_factor = %d", hw_resource->extra_fudge_factor);
+
+  if (hw_resource->separate_rotator || hw_resource->num_dma_pipe) {
+    GetHWRotatorInfo(hw_resource);
+  }
+
+  if (hw_resource->has_dyn_bw_support) {
+    DisplayError ret = GetDynamicBWLimits(hw_resource);
+    if (ret != kErrorNone) {
+      DLOGE("Failed to read dynamic band width info");
+      return ret;
+    }
+
+    DLOGI("Has Support for multiple bw limits shown below");
+    for (int index = 0; index < kBwModeMax; index++) {
+      DLOGI("Mode-index=%d  total_bw_limit=%d and pipe_bw_limit=%d", index,
+            hw_resource->dyn_bw_info.total_bw_limit[index],
+            hw_resource->dyn_bw_info.pipe_bw_limit[index]);
+    }
+  }
+
+  if (!hw_resource_) {
+    hw_resource_ = new HWResourceInfo();
+    *hw_resource_ = *hw_resource;
+  }
+
+  return kErrorNone;
+}
+
+void HWInfoDRM::GetSystemInfo(HWResourceInfo *hw_resource) {
+  DRMCrtcInfo info;
+  drm_mgr_intf_->GetCrtcInfo(0 /* system_info */, &info);
+  hw_resource->is_src_split = info.has_src_split;
+  hw_resource->has_qseed3 = (info.qseed_version == sde_drm::QSEEDVersion::V3);
+  hw_resource->num_blending_stages = info.max_blend_stages;
+  hw_resource->smart_dma_rev = (info.smart_dma_rev == sde_drm::SmartDMARevision::V2) ?
+    SmartDMARevision::V2 : SmartDMARevision::V1;
+  hw_resource->ib_fudge_factor = info.ib_fudge_factor;
+  hw_resource->hw_dest_scalar_info.prefill_lines = info.dest_scale_prefill_lines;
+  hw_resource->undersized_prefill_lines = info.undersized_prefill_lines;
+  hw_resource->macrotile_factor = info.macrotile_prefill_lines;
+  hw_resource->macrotile_nv12_factor = info.nv12_prefill_lines;
+  hw_resource->linear_factor = info.linear_prefill_lines;
+  hw_resource->scale_factor = info.downscale_prefill_lines;
+  hw_resource->extra_fudge_factor = info.extra_prefill_lines;
+  hw_resource->amortizable_threshold = info.amortized_threshold;
+  hw_resource->max_bandwidth_low = info.max_bandwidth_low / kKiloUnit;
+  hw_resource->max_bandwidth_high = info.max_bandwidth_high / kKiloUnit;
+  hw_resource->max_sde_clk = info.max_sde_clk;
+
+  std::vector<LayerBufferFormat> sdm_format;
+  for (auto &it : info.comp_ratio_rt_map) {
+    std::pair<uint32_t, uint64_t> drm_format = it.first;
+    GetSDMFormat(drm_format.first, drm_format.second, &sdm_format);
+    hw_resource->comp_ratio_rt_map.insert(std::make_pair(sdm_format[0], it.second));
+    sdm_format.clear();
+  }
+
+  for (auto &it : info.comp_ratio_nrt_map) {
+    std::pair<uint32_t, uint64_t> drm_format = it.first;
+    GetSDMFormat(drm_format.first, drm_format.second, &sdm_format);
+    hw_resource->comp_ratio_rt_map.insert(std::make_pair(sdm_format[0], it.second));
+    sdm_format.clear();
+  }
+}
+
+void HWInfoDRM::GetHWPlanesInfo(HWResourceInfo *hw_resource) {
+  DRMPlanesInfo planes;
+  drm_mgr_intf_->GetPlanesInfo(&planes);
+  for (auto &pipe_obj : planes) {
+    HWPipeCaps pipe_caps;
+    string name = {};
+    switch (pipe_obj.second.type) {
+      case DRMPlaneType::DMA:
+        name = "DMA";
+        pipe_caps.type = kPipeTypeDMA;
+        if (!hw_resource->num_dma_pipe) {
+          PopulateSupportedFmts(kHWDMAPipe, pipe_obj.second, hw_resource);
+        }
+        hw_resource->num_dma_pipe++;
+        break;
+      case DRMPlaneType::VIG:
+        name = "VIG";
+        pipe_caps.type = kPipeTypeVIG;
+        if (!hw_resource->num_vig_pipe) {
+          PopulatePipeCaps(pipe_obj.second, hw_resource);
+          PopulateSupportedFmts(kHWVIGPipe, pipe_obj.second, hw_resource);
+        }
+        hw_resource->num_vig_pipe++;
+        break;
+      case DRMPlaneType::CURSOR:
+        name = "CURSOR";
+        pipe_caps.type = kPipeTypeCursor;
+        if (!hw_resource->num_cursor_pipe) {
+          PopulateSupportedFmts(kHWCursorPipe, pipe_obj.second, hw_resource);
+          hw_resource->max_cursor_size = pipe_obj.second.max_linewidth;
+        }
+        hw_resource->num_cursor_pipe++;
+        break;
+      default:
+        continue;  // Not adding any other pipe type
+    }
+    pipe_caps.id = pipe_obj.first;
+    pipe_caps.master_pipe_id = pipe_obj.second.master_plane_id;
+    DLOGI("Adding %s Pipe : Id %d", name.c_str(), pipe_obj.first);
+    hw_resource->hw_pipes.push_back(std::move(pipe_caps));
+  }
+}
+
+void HWInfoDRM::PopulatePipeCaps(const sde_drm::DRMPlaneTypeInfo &info,
+                                    HWResourceInfo *hw_resource) {
+  hw_resource->max_pipe_width = info.max_linewidth;
+  hw_resource->max_scale_down = info.max_downscale;
+  hw_resource->max_scale_up = info.max_upscale;
+  hw_resource->has_decimation = info.max_horizontal_deci > 1 && info.max_vertical_deci > 1;
+  hw_resource->max_pipe_bw = info.max_pipe_bandwidth / kKiloUnit;
+}
+
+void HWInfoDRM::PopulateSupportedFmts(HWSubBlockType sub_blk_type,
+                                      const sde_drm::DRMPlaneTypeInfo  &info,
+                                      HWResourceInfo *hw_resource) {
+  vector<LayerBufferFormat> sdm_formats = {};
+  FormatsMap &fmts_map = hw_resource->supported_formats_map;
+
+  if (fmts_map.find(sub_blk_type) == fmts_map.end()) {
+    for (auto &fmts : info.formats_supported) {
+      GetSDMFormat(fmts.first, fmts.second, &sdm_formats);
+    }
+
+    fmts_map.insert(make_pair(sub_blk_type, sdm_formats));
+  }
+}
+
+void HWInfoDRM::GetWBInfo(HWResourceInfo *hw_resource) {
+  HWSubBlockType sub_blk_type = kHWWBIntfOutput;
+  vector<LayerBufferFormat> supported_sdm_formats = {};
+  sde_drm::DRMDisplayToken token;
+
+  // Fake register
+  if (drm_mgr_intf_->RegisterDisplay(sde_drm::DRMDisplayType::VIRTUAL, &token)) {
+    return;
+  }
+
+  sde_drm::DRMConnectorInfo connector_info;
+  drm_mgr_intf_->GetConnectorInfo(token.conn_id, &connector_info);
+  for (auto &fmts : connector_info.formats_supported) {
+    GetSDMFormat(fmts.first, fmts.second, &supported_sdm_formats);
+  }
+
+  hw_resource->supported_formats_map.erase(sub_blk_type);
+  hw_resource->supported_formats_map.insert(make_pair(sub_blk_type, supported_sdm_formats));
+
+  drm_mgr_intf_->UnregisterDisplay(token);
+}
+
+void HWInfoDRM::GetSDMFormat(uint32_t v4l2_format, LayerBufferFormat *sdm_format) {
+  switch (v4l2_format) {
+    case SDE_PIX_FMT_ARGB_8888:         *sdm_format = kFormatARGB8888;                 break;
+    case SDE_PIX_FMT_RGBA_8888:         *sdm_format = kFormatRGBA8888;                 break;
+    case SDE_PIX_FMT_BGRA_8888:         *sdm_format = kFormatBGRA8888;                 break;
+    case SDE_PIX_FMT_RGBX_8888:         *sdm_format = kFormatRGBX8888;                 break;
+    case SDE_PIX_FMT_BGRX_8888:         *sdm_format = kFormatBGRX8888;                 break;
+    case SDE_PIX_FMT_RGBA_5551:         *sdm_format = kFormatRGBA5551;                 break;
+    case SDE_PIX_FMT_RGBA_4444:         *sdm_format = kFormatRGBA4444;                 break;
+    case SDE_PIX_FMT_RGB_888:           *sdm_format = kFormatRGB888;                   break;
+    case SDE_PIX_FMT_BGR_888:           *sdm_format = kFormatBGR888;                   break;
+    case SDE_PIX_FMT_RGB_565:           *sdm_format = kFormatRGB565;                   break;
+    case SDE_PIX_FMT_BGR_565:           *sdm_format = kFormatBGR565;                   break;
+    case SDE_PIX_FMT_Y_CB_CR_H2V2:      *sdm_format = kFormatYCbCr420Planar;           break;
+    case SDE_PIX_FMT_Y_CR_CB_H2V2:      *sdm_format = kFormatYCrCb420Planar;           break;
+    case SDE_PIX_FMT_Y_CR_CB_GH2V2:     *sdm_format = kFormatYCrCb420PlanarStride16;   break;
+    case SDE_PIX_FMT_Y_CBCR_H2V2:       *sdm_format = kFormatYCbCr420SemiPlanar;       break;
+    case SDE_PIX_FMT_Y_CRCB_H2V2:       *sdm_format = kFormatYCrCb420SemiPlanar;       break;
+    case SDE_PIX_FMT_Y_CBCR_H1V2:       *sdm_format = kFormatYCbCr422H1V2SemiPlanar;   break;
+    case SDE_PIX_FMT_Y_CRCB_H1V2:       *sdm_format = kFormatYCrCb422H1V2SemiPlanar;   break;
+    case SDE_PIX_FMT_Y_CBCR_H2V1:       *sdm_format = kFormatYCbCr422H2V1SemiPlanar;   break;
+    case SDE_PIX_FMT_Y_CRCB_H2V1:       *sdm_format = kFormatYCrCb422H2V1SemiPlanar;   break;
+    case SDE_PIX_FMT_YCBYCR_H2V1:       *sdm_format = kFormatYCbCr422H2V1Packed;       break;
+    case SDE_PIX_FMT_Y_CBCR_H2V2_VENUS: *sdm_format = kFormatYCbCr420SemiPlanarVenus;  break;
+    case SDE_PIX_FMT_Y_CRCB_H2V2_VENUS: *sdm_format = kFormatYCrCb420SemiPlanarVenus;  break;
+    case SDE_PIX_FMT_RGBA_8888_UBWC:    *sdm_format = kFormatRGBA8888Ubwc;             break;
+    case SDE_PIX_FMT_RGBX_8888_UBWC:    *sdm_format = kFormatRGBX8888Ubwc;             break;
+    case SDE_PIX_FMT_RGB_565_UBWC:      *sdm_format = kFormatBGR565Ubwc;               break;
+    case SDE_PIX_FMT_Y_CBCR_H2V2_UBWC:  *sdm_format = kFormatYCbCr420SPVenusUbwc;      break;
+    case SDE_PIX_FMT_RGBA_1010102:      *sdm_format = kFormatRGBA1010102;              break;
+    case SDE_PIX_FMT_ARGB_2101010:      *sdm_format = kFormatARGB2101010;              break;
+    case SDE_PIX_FMT_RGBX_1010102:      *sdm_format = kFormatRGBX1010102;              break;
+    case SDE_PIX_FMT_XRGB_2101010:      *sdm_format = kFormatXRGB2101010;              break;
+    case SDE_PIX_FMT_BGRA_1010102:      *sdm_format = kFormatBGRA1010102;              break;
+    case SDE_PIX_FMT_ABGR_2101010:      *sdm_format = kFormatABGR2101010;              break;
+    case SDE_PIX_FMT_BGRX_1010102:      *sdm_format = kFormatBGRX1010102;              break;
+    case SDE_PIX_FMT_XBGR_2101010:      *sdm_format = kFormatXBGR2101010;              break;
+    case SDE_PIX_FMT_RGBA_1010102_UBWC: *sdm_format = kFormatRGBA1010102Ubwc;          break;
+    case SDE_PIX_FMT_RGBX_1010102_UBWC: *sdm_format = kFormatRGBX1010102Ubwc;          break;
+    case SDE_PIX_FMT_Y_CBCR_H2V2_P010:  *sdm_format = kFormatYCbCr420P010;             break;
+    case SDE_PIX_FMT_Y_CBCR_H2V2_TP10_UBWC: *sdm_format = kFormatYCbCr420TP10Ubwc;     break;
+    /* TODO(user) : enable when defined in uapi
+      case SDE_PIX_FMT_Y_CBCR_H2V2_P010_UBWC: *sdm_format = kFormatYCbCr420P010Ubwc;     break; */
+    default: *sdm_format = kFormatInvalid;
+  }
+}
+
+void HWInfoDRM::GetRotatorFormatsForType(int fd, uint32_t type,
+                                         vector<LayerBufferFormat> *supported_formats) {
+  struct v4l2_fmtdesc fmtdesc = {};
+  fmtdesc.type = type;
+  while (!Sys::ioctl_(fd, static_cast<int>(VIDIOC_ENUM_FMT), &fmtdesc)) {
+    LayerBufferFormat sdm_format = kFormatInvalid;
+    GetSDMFormat(fmtdesc.pixelformat, &sdm_format);
+    if (sdm_format != kFormatInvalid) {
+      supported_formats->push_back(sdm_format);
+    }
+    fmtdesc.index++;
+  }
+}
+
+DisplayError HWInfoDRM::GetRotatorSupportedFormats(uint32_t v4l2_index,
+                                                   HWResourceInfo *hw_resource) {
+  string path = "/dev/video" + to_string(v4l2_index);
+  int fd = Sys::open_(path.c_str(), O_RDONLY);
+  if (fd < 0) {
+    DLOGE("Failed to open %s with error %d", path.c_str(), errno);
+    return kErrorNotSupported;
+  }
+
+  vector<LayerBufferFormat> supported_formats = {};
+  GetRotatorFormatsForType(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT, &supported_formats);
+  hw_resource->supported_formats_map.erase(kHWRotatorInput);
+  hw_resource->supported_formats_map.insert(make_pair(kHWRotatorInput, supported_formats));
+
+  supported_formats = {};
+  GetRotatorFormatsForType(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, &supported_formats);
+  hw_resource->supported_formats_map.erase(kHWRotatorOutput);
+  hw_resource->supported_formats_map.insert(make_pair(kHWRotatorOutput, supported_formats));
+
+  Sys::close_(fd);
+
+  return kErrorNone;
+}
+
+DisplayError HWInfoDRM::GetHWRotatorInfo(HWResourceInfo *hw_resource) {
+  string v4l2_path = "/sys/class/video4linux/video";
+  const uint32_t kMaxV4L2Nodes = 64;
+
+  for (uint32_t i = 0; i < kMaxV4L2Nodes; i++) {
+    string path = v4l2_path + to_string(i) + "/name";
+    Sys::fstream fs(path, fstream::in);
+    if (!fs.is_open()) {
+      continue;
+    }
+
+    string line;
+    if (Sys::getline_(fs, line) && (!strncmp(line.c_str(), "sde_rotator", strlen("sde_rotator")))) {
+      hw_resource->hw_rot_info.device_path = string("/dev/video" + to_string(i));
+      hw_resource->hw_rot_info.num_rotator++;
+      hw_resource->hw_rot_info.type = HWRotatorInfo::ROT_TYPE_V4L2;
+      hw_resource->hw_rot_info.has_downscale = true;
+      GetRotatorSupportedFormats(i, hw_resource);
+
+      string caps_path = v4l2_path + to_string(i) + "/device/caps";
+      Sys::fstream caps_fs(caps_path, fstream::in);
+
+      if (caps_fs.is_open()) {
+        string caps;
+        while (Sys::getline_(caps_fs, caps)) {
+          const string downscale_compression = "downscale_compression=";
+          const string min_downscale = "min_downscale=";
+          if (caps.find(downscale_compression) != string::npos) {
+            hw_resource->hw_rot_info.downscale_compression =
+              std::stoi(string(caps, downscale_compression.length()));
+          } else if (caps.find(min_downscale) != string::npos) {
+            hw_resource->hw_rot_info.min_downscale =
+              std::stof(string(caps, min_downscale.length()));
+          }
+        }
+      }
+
+      // We support only 1 rotator
+      break;
+    }
+  }
+
+  DLOGI("V4L2 Rotator: Count = %d, Downscale = %d, Min_downscale = %f, Downscale_compression = %d",
+        hw_resource->hw_rot_info.num_rotator, hw_resource->hw_rot_info.has_downscale,
+        hw_resource->hw_rot_info.min_downscale, hw_resource->hw_rot_info.downscale_compression);
+
+  return kErrorNone;
+}
+
+void HWInfoDRM::GetSDMFormat(uint32_t drm_format, uint64_t drm_format_modifier,
+                             vector<LayerBufferFormat> *sdm_formats) {
+  vector<LayerBufferFormat> &fmts(*sdm_formats);
+  switch (drm_format) {
+    case DRM_FORMAT_BGRA8888:
+      fmts.push_back(kFormatARGB8888);
+      break;
+    case DRM_FORMAT_ABGR8888:
+      fmts.push_back(drm_format_modifier ? kFormatRGBA8888Ubwc : kFormatRGBA8888);
+      break;
+    case DRM_FORMAT_ARGB8888:
+      fmts.push_back(kFormatBGRA8888);
+      break;
+    case DRM_FORMAT_BGRX8888:
+      fmts.push_back(kFormatXRGB8888);
+      break;
+    case DRM_FORMAT_XBGR8888:
+      fmts.push_back(drm_format_modifier ? kFormatRGBX8888Ubwc : kFormatRGBX8888);
+      break;
+    case DRM_FORMAT_XRGB8888:
+      fmts.push_back(kFormatBGRX8888);
+      break;
+    case DRM_FORMAT_ABGR1555:
+      fmts.push_back(kFormatRGBA5551);
+      break;
+    case DRM_FORMAT_ABGR4444:
+      fmts.push_back(kFormatRGBA4444);
+      break;
+    case DRM_FORMAT_BGR888:
+      fmts.push_back(kFormatRGB888);
+      break;
+    case DRM_FORMAT_RGB888:
+      fmts.push_back(kFormatBGR888);
+      break;
+    case DRM_FORMAT_BGR565:
+      fmts.push_back(drm_format_modifier ? kFormatBGR565Ubwc : kFormatRGB565);
+      break;
+    case DRM_FORMAT_RGB565:
+      fmts.push_back(kFormatBGR565);
+      break;
+    case DRM_FORMAT_ABGR2101010:
+      fmts.push_back(drm_format_modifier ? kFormatRGBA1010102Ubwc : kFormatRGBA1010102);
+      break;
+    case DRM_FORMAT_BGRA1010102:
+      fmts.push_back(kFormatARGB2101010);
+      break;
+    case DRM_FORMAT_XBGR2101010:
+      fmts.push_back(drm_format_modifier ? kFormatRGBX1010102Ubwc : kFormatRGBX1010102);
+      break;
+    case DRM_FORMAT_BGRX1010102:
+      fmts.push_back(kFormatXRGB2101010);
+      break;
+    case DRM_FORMAT_ARGB2101010:
+      fmts.push_back(kFormatBGRA1010102);
+      break;
+    case DRM_FORMAT_RGBA1010102:
+      fmts.push_back(kFormatABGR2101010);
+      break;
+    case DRM_FORMAT_XRGB2101010:
+      fmts.push_back(kFormatBGRX1010102);
+      break;
+    case DRM_FORMAT_RGBX1010102:
+      fmts.push_back(kFormatXBGR2101010);
+      break;
+    case DRM_FORMAT_YVU420:
+      fmts.push_back(kFormatYCrCb420PlanarStride16);
+      break;
+    case DRM_FORMAT_NV12:
+      if (drm_format_modifier == (DRM_FORMAT_MOD_QCOM_COMPRESSED |
+          DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_TIGHT)) {
+          fmts.push_back(kFormatYCbCr420TP10Ubwc);
+      } else if (drm_format_modifier == (DRM_FORMAT_MOD_QCOM_COMPRESSED |
+                                         DRM_FORMAT_MOD_QCOM_DX)) {
+        fmts.push_back(kFormatYCbCr420P010Ubwc);
+      } else if (drm_format_modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED) {
+         fmts.push_back(kFormatYCbCr420SPVenusUbwc);
+      } else if (drm_format_modifier == DRM_FORMAT_MOD_QCOM_DX) {
+         fmts.push_back(kFormatYCbCr420P010);
+      } else {
+         fmts.push_back(kFormatYCbCr420SemiPlanarVenus);
+         fmts.push_back(kFormatYCbCr420SemiPlanar);
+      }
+      break;
+    case DRM_FORMAT_NV21:
+      fmts.push_back(kFormatYCrCb420SemiPlanarVenus);
+      fmts.push_back(kFormatYCrCb420SemiPlanar);
+      break;
+    case DRM_FORMAT_NV16:
+      fmts.push_back(kFormatYCbCr422H2V1SemiPlanar);
+      break;
+    default:
+      break;
+  }
+}
+
+DisplayError HWInfoDRM::GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) {
+  hw_disp_info->type = kPrimary;
+  hw_disp_info->is_connected = true;
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/drm/hw_info_drm.h b/sdm845/sdm/libs/core/drm/hw_info_drm.h
new file mode 100644
index 0000000..5d92c41
--- /dev/null
+++ b/sdm845/sdm/libs/core/drm/hw_info_drm.h
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2017, 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_DRM_H__
+#define __HW_INFO_DRM_H__
+
+#include <core/core_interface.h>
+#include <core/sdm_types.h>
+#include <drm_interface.h>
+#include <private/hw_info_types.h>
+#include <bitset>
+#include <vector>
+
+#include "hw_info_interface.h"
+
+namespace sdm {
+
+class HWInfoDRM: public HWInfoInterface {
+ public:
+  HWInfoDRM();
+  virtual ~HWInfoDRM();
+  virtual DisplayError GetHWResourceInfo(HWResourceInfo *hw_resource);
+  virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info);
+
+ private:
+  DisplayError GetHWRotatorInfo(HWResourceInfo *hw_resource);
+  void GetSystemInfo(HWResourceInfo *hw_resource);
+  void GetHWPlanesInfo(HWResourceInfo *hw_resource);
+  void GetWBInfo(HWResourceInfo *hw_resource);
+  DisplayError GetDynamicBWLimits(HWResourceInfo *hw_resource);
+  void GetSDMFormat(uint32_t drm_format, uint64_t drm_format_modifier,
+                    std::vector<LayerBufferFormat> *sdm_formats);
+  void GetSDMFormat(uint32_t v4l2_format, LayerBufferFormat *sdm_format);
+  void GetRotatorFormatsForType(int fd, uint32_t type,
+                                std::vector<LayerBufferFormat> *supported_formats);
+  DisplayError GetRotatorSupportedFormats(uint32_t v4l2_index, HWResourceInfo *hw_resource);
+  void PopulateSupportedFmts(HWSubBlockType sub_blk_type, const sde_drm::DRMPlaneTypeInfo  &info,
+                             HWResourceInfo *hw_resource);
+  void PopulatePipeCaps(const sde_drm::DRMPlaneTypeInfo &info, HWResourceInfo *hw_resource);
+
+
+  sde_drm::DRMManagerInterface *drm_mgr_intf_ = {};
+  bool default_mode_ = false;
+
+  // TODO(user): Read Mdss version from the driver
+  static const int kHWMdssVersion5 = 500;  // MDSS_V5
+  static const int kMaxStringLength = 1024;
+  static const int kKiloUnit = 1000;
+
+  static HWResourceInfo *hw_resource_;
+};
+
+}  // namespace sdm
+
+#endif  // __HW_INFO_DRM_H__
diff --git a/sdm845/sdm/libs/core/drm/hw_scale_drm.cpp b/sdm845/sdm/libs/core/drm/hw_scale_drm.cpp
new file mode 100644
index 0000000..96f084e
--- /dev/null
+++ b/sdm845/sdm/libs/core/drm/hw_scale_drm.cpp
@@ -0,0 +1,157 @@
+/*
+* Copyright (c) 2016-2017, 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/debug.h>
+
+#include "hw_scale_drm.h"
+
+#define __CLASS__ "HWScaleDRM"
+
+namespace sdm {
+
+static uint32_t GetScalingFilter(ScalingFilterConfig filter_cfg) {
+  switch (filter_cfg) {
+    case kFilterEdgeDirected:
+      return FILTER_EDGE_DIRECTED_2D;
+    case kFilterCircular:
+      return FILTER_CIRCULAR_2D;
+    case kFilterSeparable:
+      return FILTER_SEPARABLE_1D;
+    case kFilterBilinear:
+      return FILTER_BILINEAR;
+    default:
+      DLOGE("Invalid Scaling Filter");
+      return kFilterMax;
+  }
+}
+
+static uint32_t GetAlphaInterpolation(HWAlphaInterpolation alpha_filter_cfg) {
+  switch (alpha_filter_cfg) {
+    case kInterpolationPixelRepeat:
+      return FILTER_ALPHA_DROP_REPEAT;
+    case kInterpolationBilinear:
+      return FILTER_ALPHA_BILINEAR;
+    default:
+      DLOGE("Invalid Alpha Interpolation");
+      return kInterpolationMax;
+  }
+}
+
+void HWScaleDRM::SetPlaneScaler(const HWScaleData &scale_data, SDEScaler *scaler) {
+  if (version_ == Version::V2) {
+    SetPlaneScalerV2(scale_data, &scaler->scaler_v2);
+  }
+}
+
+void HWScaleDRM::SetPlaneScalerV2(const HWScaleData &scale_data, sde_drm_scaler_v2 *scaler) {
+  if (!scale_data.enable.scale && !scale_data.enable.direction_detection &&
+      !scale_data.enable.detail_enhance) {
+    return;
+  }
+
+  scaler->enable = scale_data.enable.scale;
+  scaler->dir_en = scale_data.enable.direction_detection;
+  scaler->de.enable = scale_data.detail_enhance.enable;
+
+  for (int i = 0; i < SDE_MAX_PLANES; i++) {
+    const HWPlane &plane = scale_data.plane[i];
+    scaler->init_phase_x[i] = plane.init_phase_x;
+    scaler->phase_step_x[i] = plane.phase_step_x;
+    scaler->init_phase_y[i] = plane.init_phase_y;
+    scaler->phase_step_y[i] = plane.phase_step_y;
+
+    // TODO(user): Remove right, bottom from HWPlane and rename to LR, TB similar to qseed3
+    // Also remove roi_width which is unused.
+    scaler->pe.num_ext_pxls_lr[i] = plane.left.extension;
+    scaler->pe.num_ext_pxls_tb[i] = plane.top.extension;
+
+    scaler->pe.left_ftch[i] = plane.left.overfetch;
+    scaler->pe.top_ftch[i] = plane.top.overfetch;
+    scaler->pe.right_ftch[i] = plane.right.overfetch;
+    scaler->pe.btm_ftch[i] = plane.bottom.overfetch;
+
+    scaler->pe.left_rpt[i] = plane.left.repeat;
+    scaler->pe.top_rpt[i] = plane.top.repeat;
+    scaler->pe.right_rpt[i] = plane.right.repeat;
+    scaler->pe.btm_rpt[i] = plane.bottom.repeat;
+
+    scaler->preload_x[i] = UINT32(plane.preload_x);
+    scaler->preload_y[i] = UINT32(plane.preload_y);
+
+    scaler->src_width[i] = plane.src_width;
+    scaler->src_height[i] = plane.src_height;
+  }
+
+  scaler->dst_width = scale_data.dst_width;
+  scaler->dst_height = scale_data.dst_height;
+
+  scaler->y_rgb_filter_cfg = GetScalingFilter(scale_data.y_rgb_filter_cfg);
+  scaler->uv_filter_cfg = GetScalingFilter(scale_data.uv_filter_cfg);
+  scaler->alpha_filter_cfg = GetAlphaInterpolation(scale_data.alpha_filter_cfg);
+  scaler->blend_cfg = scale_data.blend_cfg;
+
+  scaler->lut_flag = (scale_data.lut_flag.lut_swap ? SCALER_LUT_SWAP : 0) |
+                     (scale_data.lut_flag.lut_dir_wr ? SCALER_LUT_DIR_WR : 0) |
+                     (scale_data.lut_flag.lut_y_cir_wr ? SCALER_LUT_Y_CIR_WR : 0) |
+                     (scale_data.lut_flag.lut_uv_cir_wr ? SCALER_LUT_UV_CIR_WR : 0) |
+                     (scale_data.lut_flag.lut_y_sep_wr ? SCALER_LUT_Y_SEP_WR : 0) |
+                     (scale_data.lut_flag.lut_uv_sep_wr ? SCALER_LUT_UV_SEP_WR : 0);
+
+  scaler->dir_lut_idx = scale_data.dir_lut_idx;
+  scaler->y_rgb_cir_lut_idx = scale_data.y_rgb_cir_lut_idx;
+  scaler->uv_cir_lut_idx = scale_data.uv_cir_lut_idx;
+  scaler->y_rgb_sep_lut_idx = scale_data.y_rgb_sep_lut_idx;
+  scaler->uv_sep_lut_idx = scale_data.uv_sep_lut_idx;
+
+  /* TODO(user): Uncomment when de support is added
+  if (scaler->de.enable) {
+    sde_drm_de_v1 *det_enhance = &scaler->de;
+    det_enhance->sharpen_level1 = scale_data.detail_enhance.sharpen_level1;
+    det_enhance->sharpen_level2 = scale_data.detail_enhance.sharpen_level2;
+    det_enhance->clip = scale_data.detail_enhance.clip;
+    det_enhance->limit = scale_data.detail_enhance.limit;
+    det_enhance->thr_quiet = scale_data.detail_enhance.thr_quiet;
+    det_enhance->thr_dieout = scale_data.detail_enhance.thr_dieout;
+    det_enhance->thr_low = scale_data.detail_enhance.thr_low;
+    det_enhance->thr_high = scale_data.detail_enhance.thr_high;
+    det_enhance->prec_shift = scale_data.detail_enhance.prec_shift;
+
+    for (int i = 0; i < SDE_MAX_DE_CURVES; i++) {
+      det_enhance->adjust_a[i] = scale_data.detail_enhance.adjust_a[i];
+      det_enhance->adjust_b[i] = scale_data.detail_enhance.adjust_b[i];
+      det_enhance->adjust_c[i] = scale_data.detail_enhance.adjust_c[i];
+    }
+  }
+  */
+
+  return;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/drm/hw_scale_drm.h b/sdm845/sdm/libs/core/drm/hw_scale_drm.h
new file mode 100644
index 0000000..8a4be70
--- /dev/null
+++ b/sdm845/sdm/libs/core/drm/hw_scale_drm.h
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2016-2017, 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_SCALE_DRM_H__
+#define __HW_SCALE_DRM_H__
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <drm.h>
+// The 3 headers above are a workaround to prevent kernel drm.h from being used that has the
+// "virtual" keyword used for a variable. In future replace libdrm version drm.h with kernel
+// version drm/drm.h
+#include <drm/sde_drm.h>
+#include <private/hw_info_types.h>
+
+namespace sdm {
+
+struct SDEScaler {
+  struct sde_drm_scaler_v2 scaler_v2 = {};
+  // More here, maybe in a union
+};
+
+class HWScaleDRM {
+ public:
+  enum class Version { V2 };
+  explicit HWScaleDRM(Version v) : version_(v) {}
+  void SetPlaneScaler(const HWScaleData &scale, SDEScaler *scaler);
+
+ private:
+  void SetPlaneScalerV2(const HWScaleData &scale, sde_drm_scaler_v2 *scaler_v2);
+
+  Version version_ = Version::V2;
+};
+
+}  // namespace sdm
+
+#endif  // __HW_SCALE_DRM_H__
diff --git a/sdm845/sdm/libs/core/drm/hw_virtual_drm.cpp b/sdm845/sdm/libs/core/drm/hw_virtual_drm.cpp
new file mode 100644
index 0000000..5fe1d86
--- /dev/null
+++ b/sdm845/sdm/libs/core/drm/hw_virtual_drm.cpp
@@ -0,0 +1,188 @@
+/*
+Copyright (c) 2017, 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 <ctype.h>
+#include <drm_logger.h>
+#include <utils/debug.h>
+#include "hw_device_drm.h"
+#include "hw_virtual_drm.h"
+#include "hw_info_drm.h"
+
+#define __CLASS__ "HWVirtualDRM"
+
+using sde_drm::DRMDisplayType;
+using sde_drm::DRMConnectorInfo;
+using sde_drm::DRMRect;
+using sde_drm::DRMOps;
+
+namespace sdm {
+
+HWVirtualDRM::HWVirtualDRM(BufferSyncHandler *buffer_sync_handler,
+                           BufferAllocator *buffer_allocator,
+                           HWInfoInterface *hw_info_intf)
+                           : HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf) {
+  HWDeviceDRM::deferred_initialize_ = true;
+  HWDeviceDRM::device_name_ = "Virtual Display Device";
+  HWDeviceDRM::hw_info_intf_ = hw_info_intf;
+  HWDeviceDRM::disp_type_ = DRMDisplayType::VIRTUAL;
+}
+
+DisplayError HWVirtualDRM::Init() {
+  return kErrorNone;
+}
+
+DisplayError HWVirtualDRM::DeferredInit() {
+  if (HWDeviceDRM::Init() != kErrorNone)
+    return kErrorResources;
+
+  drm_mgr_intf_->SetScalerLUT(drm_lut_info_);
+  DLOGI_IF(kTagDriverConfig, "Setup CRTC %d, Connector %d for %s",
+            token_.crtc_id, token_.conn_id, device_name_);
+
+  return kErrorNone;
+}
+
+void HWVirtualDRM::ConfigureWbConnectorFbId(uint32_t fb_id) {
+  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_OUTPUT_FB_ID, token_.conn_id, fb_id);
+  return;
+}
+
+void HWVirtualDRM::ConfigureWbConnectorDestRect() {
+  DRMRect dst = {};
+  dst.left = 0;
+  dst.bottom = height_;
+  dst.top = 0;
+  dst.right = width_;
+  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_OUTPUT_RECT, token_.conn_id, dst);
+  return;
+}
+
+void HWVirtualDRM::InitializeConfigs() {
+  current_mode_.hdisplay = current_mode_.hsync_start = current_mode_.hsync_end \
+  = current_mode_.htotal = (uint16_t) width_;
+  current_mode_.vdisplay = current_mode_.vsync_start = current_mode_.vsync_end \
+  = current_mode_.vtotal = (uint16_t) height_;
+  // Not sure SF has a way to configure refresh rate. Hardcoding to 60 fps for now.
+  // TODO(user): Make this configurable.
+  current_mode_.vrefresh = 60;
+  current_mode_.clock = (current_mode_.htotal * current_mode_.vtotal \
+  * current_mode_.vrefresh) / 1000;
+  struct sde_drm_wb_cfg wb_cfg;
+  wb_cfg.connector_id = token_.conn_id;
+  wb_cfg.flags |= SDE_DRM_WB_CFG_FLAGS_CONNECTED;
+  wb_cfg.count_modes = 1;
+  wb_cfg.modes = (uint64_t)&current_mode_;
+  #ifdef DRM_IOCTL_SDE_WB_CONFIG
+  int ret = drmIoctl(dev_fd_, DRM_IOCTL_SDE_WB_CONFIG, &wb_cfg);
+  #endif
+  if (ret) {
+    DLOGE("WB config failed\n");
+  } else {
+    drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
+    current_mode_ = connector_info_.modes[0];
+    DumpConfigs();
+  }
+}
+
+void HWVirtualDRM::DumpConfigs() {
+  for (uint32_t i = 0; i < (uint32_t)connector_info_.num_modes; i++) {
+  DLOGI(
+    "Name: %s\tvref: %d\thdisp: %d\t hsync_s: %d\thsync_e:%d\thtotal: %d\t"
+    "vdisp: %d\tvsync_s: %d\tvsync_e: %d\tvtotal: %d\n",
+    connector_info_.modes[i].name, connector_info_.modes[i].vrefresh,
+    connector_info_.modes[i].hdisplay,
+    connector_info_.modes[i].hsync_start, connector_info_.modes[i].hsync_end,
+    connector_info_.modes[i].htotal, connector_info_.modes[i].vdisplay,
+    connector_info_.modes[i].vsync_start, connector_info_.modes[i].vsync_end,
+    connector_info_.modes[i].vtotal);
+  }
+}
+
+DisplayError HWVirtualDRM::Commit(HWLayers *hw_layers) {
+  LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+  DisplayError err = kErrorNone;
+
+  registry_.RegisterCurrent(hw_layers);
+  registry_.MapBufferToFbId(output_buffer);
+  uint32_t fb_id = registry_.GetFbId(output_buffer->planes[0].fd);
+
+  ConfigureWbConnectorFbId(fb_id);
+  ConfigureWbConnectorDestRect();
+
+  err = HWDeviceDRM::AtomicCommit(hw_layers);
+  registry_.UnregisterNext();
+  return(err);
+}
+
+DisplayError HWVirtualDRM::Validate(HWLayers *hw_layers) {
+  // TODO(user) : Add validate support
+  return kErrorNone;
+}
+
+
+DisplayError HWVirtualDRM::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) {
+  if (display_attributes.x_pixels == 0 || display_attributes.y_pixels == 0) {
+    return kErrorParameters;
+  }
+
+  display_attributes_ = display_attributes;
+
+  if (display_attributes_.x_pixels > hw_resource_.max_mixer_width) {
+    display_attributes_.is_device_split = true;
+  }
+
+  width_ = display_attributes_.x_pixels;
+  height_ = display_attributes_.y_pixels;
+  DeferredInit();
+
+  return kErrorNone;
+}
+
+DisplayError HWVirtualDRM::GetPPFeaturesVersion(PPFeatureVersion *vers) {
+  return kErrorNone;
+}
+
+DisplayError HWVirtualDRM::SetScaleLutConfig(HWScaleLutInfo *lut_info) {
+  drm_lut_info_.cir_lut = lut_info->cir_lut;
+  drm_lut_info_.dir_lut = lut_info->dir_lut;
+  drm_lut_info_.sep_lut = lut_info->sep_lut;
+  drm_lut_info_.cir_lut_size = lut_info->cir_lut_size;
+  drm_lut_info_.dir_lut_size = lut_info->dir_lut_size;
+  drm_lut_info_.sep_lut_size = lut_info->sep_lut_size;
+
+  // Due to differed Init in WB case, we cannot set scaler config immediately as we
+  // won't have SDE DRM initialized at this point. Hence have to cache LUT info here
+  // and set it in ::DeferredInit
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/core/drm/hw_virtual_drm.h b/sdm845/sdm/libs/core/drm/hw_virtual_drm.h
new file mode 100644
index 0000000..b63519a
--- /dev/null
+++ b/sdm845/sdm/libs/core/drm/hw_virtual_drm.h
@@ -0,0 +1,71 @@
+/*
+Copyright (c) 2017, 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_DRM_H__
+#define __HW_VIRTUAL_DRM_H__
+
+#include "hw_device_drm.h"
+#include <drm/msm_drm.h>
+#include <drm/sde_drm.h>
+
+namespace sdm {
+
+class HWVirtualDRM : public HWDeviceDRM {
+ public:
+  HWVirtualDRM(BufferSyncHandler *buffer_sync_handler,
+               BufferAllocator *buffer_allocator, HWInfoInterface *hw_info_intf);
+  virtual ~HWVirtualDRM() {}
+  virtual DisplayError SetVSyncState(bool enable) { return kErrorNotSupported; }
+  virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
+
+ protected:
+  virtual DisplayError Init();
+  virtual DisplayError Validate(HWLayers *hw_layers);
+  virtual DisplayError DeferredInit();
+  virtual void InitializeConfigs();
+  virtual DisplayError Commit(HWLayers *hw_layers);
+  virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
+  virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
+  void ConfigureWbConnectorFbId(uint32_t fb_id);
+  void ConfigureWbConnectorDestRect();
+  void DumpConfigs();
+
+ private:
+  uint32_t width_ = 0;
+  uint32_t height_ = 0;
+  sde_drm::DRMScalerLUTInfo drm_lut_info_ = {};
+};
+
+}  // namespace sdm
+
+#endif  // __HW_VIRTUAL_DRM_H__
+
diff --git a/sdm845/sdm/libs/core/dump_impl.cpp b/sdm845/sdm/libs/core/dump_impl.cpp
new file mode 100644
index 0000000..655b210
--- /dev/null
+++ b/sdm845/sdm/libs/core/dump_impl.cpp
@@ -0,0 +1,94 @@
+/*
+* Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#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));
+  // Reserve one byte for null terminating character
+  if ((filled + 1) >= length) {
+    return;
+  }
+  buffer += filled;
+
+  va_list list;
+  va_start(list, format);
+  vsnprintf(buffer, length - filled -1, 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/sdm845/sdm/libs/core/dump_impl.h b/sdm845/sdm/libs/core/dump_impl.h
new file mode 100644
index 0000000..68e7584
--- /dev/null
+++ b/sdm845/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 class DumpInterface;
+};
+
+}  // namespace sdm
+
+#endif  // __DUMP_IMPL_H__
+
diff --git a/sdm845/sdm/libs/core/fb/hw_color_manager.cpp b/sdm845/sdm/libs/core/fb/hw_color_manager.cpp
new file mode 100644
index 0000000..a6c78b0
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_color_manager.cpp
@@ -0,0 +1,166 @@
+/*
+* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <ctype.h>
+#include <math.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <sys/prctl.h>
+#include <linux/msm_mdp.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include "hw_color_manager.h"
+
+#define __CLASS__ "HWColorManager"
+
+namespace sdm {
+
+DisplayError (*HWColorManager::SetFeature[])(const PPFeatureInfo &, msmfb_mdp_pp *) = {
+        [kGlobalColorFeaturePcc] = &HWColorManager::SetPCC,
+        [kGlobalColorFeatureIgc] = &HWColorManager::SetIGC,
+        [kGlobalColorFeaturePgc] = &HWColorManager::SetPGC,
+        [kMixerColorFeatureGc] = &HWColorManager::SetMixerGC,
+        [kGlobalColorFeaturePaV2] = &HWColorManager::SetPAV2,
+        [kGlobalColorFeatureDither] = &HWColorManager::SetDither,
+        [kGlobalColorFeatureGamut] = &HWColorManager::SetGamut,
+        [kGlobalColorFeaturePADither] = &HWColorManager::SetPADither,
+};
+
+DisplayError HWColorManager::SetPCC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+  DisplayError ret = kErrorNone;
+
+  kernel_params->op = mdp_op_pcc_cfg;
+  kernel_params->data.pcc_cfg_data.version = feature.feature_version_;
+  kernel_params->data.pcc_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+  kernel_params->data.pcc_cfg_data.ops = feature.enable_flags_;
+  kernel_params->data.pcc_cfg_data.cfg_payload = feature.GetConfigData();
+  DLOGV_IF(kTagQDCM, "kernel params version = %d, block = %d, flags = %d",
+           kernel_params->data.pcc_cfg_data.version, kernel_params->data.pcc_cfg_data.block,
+           kernel_params->data.pcc_cfg_data.ops);
+
+  return ret;
+}
+
+DisplayError HWColorManager::SetIGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+  DisplayError ret = kErrorNone;
+
+  kernel_params->op = mdp_op_lut_cfg;
+  kernel_params->data.lut_cfg_data.lut_type = mdp_lut_igc;
+  kernel_params->data.lut_cfg_data.data.igc_lut_data.block =
+      MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+  kernel_params->data.lut_cfg_data.data.igc_lut_data.version = feature.feature_version_;
+  kernel_params->data.lut_cfg_data.data.igc_lut_data.ops = feature.enable_flags_;
+  kernel_params->data.lut_cfg_data.data.igc_lut_data.cfg_payload = feature.GetConfigData();
+
+  return ret;
+}
+
+DisplayError HWColorManager::SetPGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+  DisplayError ret = kErrorNone;
+
+  kernel_params->op = mdp_op_lut_cfg;
+  kernel_params->data.lut_cfg_data.lut_type = mdp_lut_pgc;
+  kernel_params->data.lut_cfg_data.data.pgc_lut_data.version = feature.feature_version_;
+  kernel_params->data.lut_cfg_data.data.pgc_lut_data.block =
+      MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+  kernel_params->data.lut_cfg_data.data.pgc_lut_data.flags = feature.enable_flags_;
+  kernel_params->data.lut_cfg_data.data.pgc_lut_data.cfg_payload = feature.GetConfigData();
+
+  return ret;
+}
+
+DisplayError HWColorManager::SetMixerGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+  DisplayError ret = kErrorNone;
+
+  kernel_params->op = mdp_op_lut_cfg;
+  kernel_params->data.lut_cfg_data.lut_type = mdp_lut_pgc;
+  kernel_params->data.lut_cfg_data.data.pgc_lut_data.version = feature.feature_version_;
+  kernel_params->data.lut_cfg_data.data.pgc_lut_data.block =
+      (MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_) | MDSS_PP_LM_CFG;
+  kernel_params->data.lut_cfg_data.data.pgc_lut_data.flags = feature.enable_flags_;
+  kernel_params->data.lut_cfg_data.data.pgc_lut_data.cfg_payload = feature.GetConfigData();
+  return ret;
+}
+
+DisplayError HWColorManager::SetPAV2(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+  DisplayError ret = kErrorNone;
+
+  kernel_params->op = mdp_op_pa_v2_cfg;
+  kernel_params->data.pa_v2_cfg_data.version = feature.feature_version_;
+  kernel_params->data.pa_v2_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+  kernel_params->data.pa_v2_cfg_data.flags = feature.enable_flags_;
+  kernel_params->data.pa_v2_cfg_data.cfg_payload = feature.GetConfigData();
+  DLOGV_IF(kTagQDCM, "kernel params version = %d, block = %d, flags = %d",
+           kernel_params->data.pa_v2_cfg_data.version, kernel_params->data.pa_v2_cfg_data.block,
+           kernel_params->data.pa_v2_cfg_data.flags);
+
+  return ret;
+}
+
+DisplayError HWColorManager::SetDither(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+  DisplayError ret = kErrorNone;
+
+  kernel_params->op = mdp_op_dither_cfg;
+  kernel_params->data.dither_cfg_data.version = feature.feature_version_;
+  kernel_params->data.dither_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+  kernel_params->data.dither_cfg_data.flags = feature.enable_flags_;
+  kernel_params->data.dither_cfg_data.cfg_payload = feature.GetConfigData();
+
+  return ret;
+}
+
+DisplayError HWColorManager::SetGamut(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
+  DisplayError ret = kErrorNone;
+
+  kernel_params->op = mdp_op_gamut_cfg;
+  kernel_params->data.gamut_cfg_data.version = feature.feature_version_;
+  kernel_params->data.gamut_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+  kernel_params->data.gamut_cfg_data.flags = feature.enable_flags_;
+  kernel_params->data.gamut_cfg_data.cfg_payload = feature.GetConfigData();
+
+  return ret;
+}
+
+DisplayError HWColorManager::SetPADither(const PPFeatureInfo &feature,
+                                         msmfb_mdp_pp *kernel_params) {
+  DisplayError ret = kErrorNone;
+#ifdef PA_DITHER
+  kernel_params->op = mdp_op_pa_dither_cfg;
+  kernel_params->data.dither_cfg_data.version = feature.feature_version_;
+  kernel_params->data.dither_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+  kernel_params->data.dither_cfg_data.flags = feature.enable_flags_;
+  kernel_params->data.dither_cfg_data.cfg_payload = feature.GetConfigData();
+#endif
+  return ret;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/fb/hw_color_manager.h b/sdm845/sdm/libs/core/fb/hw_color_manager.h
new file mode 100644
index 0000000..c9eea5b
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_color_manager.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2015-2016, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* 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_COLOR_MANAGER_H__
+#define __HW_COLOR_MANAGER_H__
+
+#include <linux/msm_mdp_ext.h>
+#include <linux/msm_mdp.h>
+
+#include <private/color_params.h>
+
+namespace sdm {
+
+class HWColorManager {
+ public:
+  static DisplayError SetPCC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+  static DisplayError SetIGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+  static DisplayError SetPGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+  static DisplayError SetMixerGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+  static DisplayError SetPAV2(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+  static DisplayError SetDither(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+  static DisplayError SetGamut(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+  static DisplayError SetPADither(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
+
+  static DisplayError (*SetFeature[kMaxNumPPFeatures])(const PPFeatureInfo &feature,
+                                                       msmfb_mdp_pp *kernel_params);
+
+ protected:
+  HWColorManager() {}
+};
+
+}  // namespace sdm
+
+#endif  // __HW_COLOR_MANAGER_H__
diff --git a/sdm845/sdm/libs/core/fb/hw_device.cpp b/sdm845/sdm/libs/core/fb/hw_device.cpp
new file mode 100644
index 0000000..773845b
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_device.cpp
@@ -0,0 +1,1363 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <stdio.h>
+#include <ctype.h>
+#include <math.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.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 <utils/sys.h>
+#include <vector>
+#include <algorithm>
+#include <string>
+
+#include "hw_device.h"
+#include "hw_primary.h"
+#include "hw_hdmi.h"
+#include "hw_virtual.h"
+#include "hw_info_interface.h"
+
+#define __CLASS__ "HWDevice"
+
+using std::string;
+using std::to_string;
+using std::fstream;
+
+namespace sdm {
+
+HWDevice::HWDevice(BufferSyncHandler *buffer_sync_handler)
+  : fb_node_index_(-1), fb_path_("/sys/devices/virtual/graphics/fb"),
+    buffer_sync_handler_(buffer_sync_handler), synchronous_commit_(false) {
+}
+
+DisplayError HWDevice::Init() {
+  // Read the fb node index
+  fb_node_index_ = GetFBNodeIndex(device_type_);
+  if (fb_node_index_ == -1) {
+    DLOGE("device type = %d should be present", device_type_);
+    return kErrorHardware;
+  }
+
+  const char *dev_name = NULL;
+  vector<string> dev_paths = {"/dev/graphics/fb", "/dev/fb"};
+  for (size_t i = 0; i < dev_paths.size(); i++) {
+    dev_paths[i] += to_string(fb_node_index_);
+    if (Sys::access_(dev_paths[i].c_str(), F_OK) >= 0) {
+      dev_name = dev_paths[i].c_str();
+      DLOGI("access(%s) successful", dev_name);
+      break;
+    }
+
+    DLOGI("access(%s), errno = %d, error = %s", dev_paths[i].c_str(), errno, strerror(errno));
+  }
+
+  if (!dev_name) {
+    DLOGE("access() failed for all possible paths");
+    return kErrorHardware;
+  }
+
+  // Populate Panel Info (Used for Partial Update)
+  PopulateHWPanelInfo();
+  // Populate HW Capabilities
+  hw_resource_ = HWResourceInfo();
+  hw_info_intf_->GetHWResourceInfo(&hw_resource_);
+
+  device_fd_ = Sys::open_(dev_name, O_RDWR);
+  if (device_fd_ < 0) {
+    DLOGE("open %s failed errno = %d, error = %s", dev_name, errno, strerror(errno));
+    return kErrorResources;
+  }
+
+  return HWScale::Create(&hw_scale_, hw_resource_.has_qseed3);
+}
+
+DisplayError HWDevice::Deinit() {
+  HWScale::Destroy(hw_scale_);
+
+  if (device_fd_ >= 0) {
+    Sys::close_(device_fd_);
+    device_fd_ = -1;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWDevice::GetActiveConfig(uint32_t *active_config) {
+  *active_config = 0;
+  return kErrorNone;
+}
+
+DisplayError HWDevice::GetNumDisplayAttributes(uint32_t *count) {
+  *count = 1;
+  return kErrorNone;
+}
+
+DisplayError HWDevice::GetDisplayAttributes(uint32_t index,
+                                            HWDisplayAttributes *display_attributes) {
+  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::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDevice::GetConfigIndex(uint32_t mode, uint32_t *index) {
+  return kErrorNone;
+}
+
+DisplayError HWDevice::PowerOn() {
+  DTRACE_SCOPED();
+
+  if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
+    if (errno == ESHUTDOWN) {
+      DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+      return kErrorShutDown;
+    }
+    IOCTL_LOGE(FB_BLANK_UNBLANK, device_type_);
+    return kErrorHardware;
+  }
+
+  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;
+  uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
+
+  DLOGV_IF(kTagDriverConfig, "************************** %s Validate Input ***********************",
+           device_name_);
+  DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_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_count; i++) {
+    const Layer &layer = hw_layer_info.hw_layers.at(i);
+    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);
+
+    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);
+
+        if (layer.flags.solid_fill) {
+          mdp_buffer.format = MDP_ARGB_8888;
+        } else {
+          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;
+#ifdef MDP_COMMIT_RECT_NUM
+        mdp_layer.rect_num = pipe_info->rect;
+#endif
+        SetRect(pipe_info->src_roi, &mdp_layer.src_rect);
+        SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect);
+        SetMDPFlags(&layer, is_rotator_used, hw_layer_info.async_cursor_updates, &mdp_layer.flags);
+        SetCSC(layer.input_buffer.color_metadata, &mdp_layer.color_space);
+        if (pipe_info->flags & kIGC) {
+          SetIGC(&layer.input_buffer, mdp_layer_count);
+        }
+        if (pipe_info->flags & kMultiRect) {
+          mdp_layer.flags |= MDP_LAYER_MULTIRECT_ENABLE;
+          if (pipe_info->flags & kMultiRectParallelMode) {
+            mdp_layer.flags |= MDP_LAYER_MULTIRECT_PARALLEL_MODE;
+          }
+        }
+        mdp_layer.bg_color = layer.solid_fill_color;
+
+        // HWScaleData to MDP driver
+        hw_scale_->SetHWScaleData(pipe_info->scale_data, mdp_layer_count, &mdp_commit,
+                                  pipe_info->sub_block_type);
+        mdp_layer.scale = hw_scale_->GetScaleDataRef(mdp_layer_count, pipe_info->sub_block_type);
+
+        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);
+        hw_scale_->DumpScaleData(mdp_layer.scale);
+        DLOGV_IF(kTagDriverConfig, "*************************************************************");
+      }
+    }
+  }
+
+  // TODO(user): This block should move to the derived class
+  if (device_type_ == kDeviceVirtual) {
+    LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+    mdp_out_layer_.writeback_ndx = hw_resource_.writeback_index;
+    mdp_out_layer_.buffer.width = output_buffer->width;
+    mdp_out_layer_.buffer.height = output_buffer->height;
+    if (output_buffer->flags.secure) {
+      mdp_out_layer_.flags |= MDP_LAYER_SECURE_SESSION;
+    }
+    mdp_out_layer_.buffer.comp_ratio.denom = 1000;
+    mdp_out_layer_.buffer.comp_ratio.numer = UINT32(hw_layers->output_compression * 1000);
+#ifdef OUT_LAYER_COLOR_SPACE
+    SetCSC(output_buffer->color_metadata, &mdp_out_layer_.color_space);
+#endif
+    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, "*****************************************************************");
+  }
+
+  uint32_t index = 0;
+  for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
+    DestScaleInfoMap::iterator it = hw_layer_info.dest_scale_info_map.find(i);
+
+    if (it == hw_layer_info.dest_scale_info_map.end()) {
+      continue;
+    }
+
+    HWDestScaleInfo *dest_scale_info = it->second;
+
+    mdp_destination_scaler_data *dest_scalar_data = &mdp_dest_scalar_data_[index];
+    hw_scale_->SetHWScaleData(dest_scale_info->scale_data, index, &mdp_commit,
+                              kHWDestinationScalar);
+
+    if (dest_scale_info->scale_update) {
+      dest_scalar_data->flags |= MDP_DESTSCALER_SCALE_UPDATE;
+    }
+
+    dest_scalar_data->dest_scaler_ndx = i;
+    dest_scalar_data->lm_width = dest_scale_info->mixer_width;
+    dest_scalar_data->lm_height = dest_scale_info->mixer_height;
+#ifdef MDP_DESTSCALER_ROI_ENABLE
+    SetRect(dest_scale_info->panel_roi, &dest_scalar_data->panel_roi);
+    dest_scalar_data->flags |= MDP_DESTSCALER_ROI_ENABLE;
+#endif
+    dest_scalar_data->scale = reinterpret_cast <uint64_t>
+      (hw_scale_->GetScaleDataRef(index, kHWDestinationScalar));
+
+    index++;
+
+    DLOGV_IF(kTagDriverConfig, "************************ DestScalar[%d] **************************",
+             dest_scalar_data->dest_scaler_ndx);
+    DLOGV_IF(kTagDriverConfig, "Mixer WxH %dx%d flags %x", dest_scalar_data->lm_width,
+             dest_scalar_data->lm_height, dest_scalar_data->flags);
+#ifdef MDP_DESTSCALER_ROI_ENABLE
+    DLOGV_IF(kTagDriverConfig, "Panel ROI [%d, %d, %d, %d]", dest_scalar_data->panel_roi.x,
+             dest_scalar_data->panel_roi.y, dest_scalar_data->panel_roi.w,
+             dest_scalar_data->panel_roi.h);
+#endif
+    DLOGV_IF(kTagDriverConfig, "*****************************************************************");
+  }
+  mdp_commit.dest_scaler_cnt = UINT32(hw_layer_info.dest_scale_info_map.size());
+
+  mdp_commit.flags |= MDP_VALIDATE_LAYER;
+#ifdef MDP_COMMIT_RECT_NUM
+  mdp_commit.flags |= MDP_COMMIT_RECT_NUM;
+#endif
+  if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) {
+    if (errno == ESHUTDOWN) {
+      DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+      return kErrorShutDown;
+    }
+    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;
+  const mdp_rect &l_roi = mdp_commit.left_roi;
+  const mdp_rect &r_roi = mdp_commit.right_roi;
+
+  DLOGI("mdp_commit: flags = %x, release fence = %x", mdp_commit.flags, mdp_commit.release_fence);
+  DLOGI("left_roi: x = %d, y = %d, w = %d, h = %d", l_roi.x, l_roi.y, l_roi.w, l_roi.h);
+  DLOGI("right_roi: x = %d, y = %d, w = %d, h = %d", r_roi.x, r_roi.y, r_roi.w, r_roi.h);
+  for (uint32_t i = 0; i < mdp_commit.dest_scaler_cnt; i++) {
+    mdp_destination_scaler_data *dest_scalar_data = &mdp_dest_scalar_data_[i];
+    mdp_scale_data_v2 *mdp_scale = reinterpret_cast<mdp_scale_data_v2 *>(dest_scalar_data->scale);
+
+    DLOGI("Dest scalar index %d Mixer WxH %dx%d", dest_scalar_data->dest_scaler_ndx,
+          dest_scalar_data->lm_width, dest_scalar_data->lm_height);
+#ifdef MDP_DESTSCALER_ROI_ENABLE
+    DLOGI("Panel ROI [%d, %d, %d, %d]", dest_scalar_data->panel_roi.x,
+           dest_scalar_data->panel_roi.y, dest_scalar_data->panel_roi.w,
+           dest_scalar_data->panel_roi.h);
+#endif
+    DLOGI("Dest scalar Dst WxH %dx%d", mdp_scale->dst_width, mdp_scale->dst_height);
+  }
+  for (uint32_t i = 0; i < mdp_commit.input_layer_cnt; i++) {
+    const mdp_input_layer &layer = mdp_layers[i];
+    const mdp_rect &src_rect = layer.src_rect;
+    const mdp_rect &dst_rect = layer.dst_rect;
+    DLOGI("layer = %d, pipe_ndx = %x, z = %d, flags = %x",
+      i, layer.pipe_ndx, layer.z_order, layer.flags);
+    DLOGI("src_width = %d, src_height = %d, src_format = %d",
+      layer.buffer.width, layer.buffer.height, layer.buffer.format);
+    DLOGI("src_rect: x = %d, y = %d, w = %d, h = %d",
+      src_rect.x, src_rect.y, src_rect.w, src_rect.h);
+    DLOGI("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;
+  uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
+
+  DLOGV_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
+           device_name_);
+  DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_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_count; i++) {
+    const Layer &layer = hw_layer_info.hw_layers.at(i);
+    LayerBuffer *input_buffer = const_cast<LayerBuffer *>(&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;
+
+    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 {
+          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, "*************************************************************");
+      }
+    }
+  }
+
+  // TODO(user): Move to derived class
+  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 {
+      DLOGE("Invalid output buffer fd");
+      return kErrorParameters;
+    }
+
+    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 &= UINT32(~MDP_VALIDATE_LAYER);
+  if (synchronous_commit_) {
+    mdp_commit.flags |= MDP_COMMIT_WAIT_FOR_FINISH;
+  }
+  if (bl_update_commit && bl_level_update_commit >= 0) {
+#ifdef MDP_COMMIT_UPDATE_BRIGHTNESS
+    mdp_commit.bl_level = (uint32_t)bl_level_update_commit;
+    mdp_commit.flags |= MDP_COMMIT_UPDATE_BRIGHTNESS;
+#endif
+  }
+  if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) {
+    if (errno == ESHUTDOWN) {
+      DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+      return kErrorShutDown;
+    }
+    IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
+    DumpLayerCommit(mdp_disp_commit_);
+    synchronous_commit_ = false;
+    return kErrorHardware;
+  }
+
+  LayerStack *stack = hw_layer_info.stack;
+  stack->retire_fence_fd = mdp_commit.retire_fence;
+#ifdef VIDEO_MODE_DEFER_RETIRE_FENCE
+  if (hw_panel_info_.mode == kModeVideo) {
+    stack->retire_fence_fd = stored_retire_fence;
+    stored_retire_fence =  mdp_commit.retire_fence;
+  }
+#endif
+  // 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_count; i++) {
+    const Layer &layer = hw_layer_info.hw_layers.at(i);
+    LayerBuffer *input_buffer = const_cast<LayerBuffer *>(&layer.input_buffer);
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+
+    if (hw_rotator_session->hw_block_count) {
+      input_buffer = &hw_rotator_session->output_buffer;
+      input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence);
+      continue;
+    }
+
+    input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence);
+  }
+
+  hw_layer_info.sync_handle = Sys::dup_(mdp_commit.release_fence);
+
+  DLOGI_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
+           device_name_);
+  DLOGI_IF(kTagDriverConfig, "retire_fence_fd %d", stack->retire_fence_fd);
+  DLOGI_IF(kTagDriverConfig, "*******************************************************************");
+
+  if (mdp_commit.release_fence >= 0) {
+    Sys::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;
+  }
+
+  if (bl_update_commit)
+    bl_update_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 &= UINT32(~MDP_VALIDATE_LAYER);
+  if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) {
+    if (errno == ESHUTDOWN) {
+      DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+      return kErrorShutDown;
+    }
+    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 kFormatBGR565:                   *target = MDP_BGR_565;           break;
+  case kFormatYCbCr420Planar:           *target = MDP_Y_CB_CR_H2V2;      break;
+  case kFormatYCrCb420Planar:           *target = MDP_Y_CR_CB_H2V2;      break;
+  case kFormatYCrCb420PlanarStride16:   *target = MDP_Y_CR_CB_GH2V2;     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 kFormatBGR565Ubwc:               *target = MDP_RGB_565_UBWC;      break;
+  case kFormatYCbCr420SPVenusUbwc:      *target = MDP_Y_CBCR_H2V2_UBWC;  break;
+  case kFormatCbYCrY422H2V1Packed:      *target = MDP_CBYCRY_H2V1;       break;
+  case kFormatRGBA1010102:              *target = MDP_RGBA_1010102;      break;
+  case kFormatARGB2101010:              *target = MDP_ARGB_2101010;      break;
+  case kFormatRGBX1010102:              *target = MDP_RGBX_1010102;      break;
+  case kFormatXRGB2101010:              *target = MDP_XRGB_2101010;      break;
+  case kFormatBGRA1010102:              *target = MDP_BGRA_1010102;      break;
+  case kFormatABGR2101010:              *target = MDP_ABGR_2101010;      break;
+  case kFormatBGRX1010102:              *target = MDP_BGRX_1010102;      break;
+  case kFormatXBGR2101010:              *target = MDP_XBGR_2101010;      break;
+  case kFormatRGBA1010102Ubwc:          *target = MDP_RGBA_1010102_UBWC; break;
+  case kFormatRGBX1010102Ubwc:          *target = MDP_RGBX_1010102_UBWC; break;
+  case kFormatYCbCr420P010:             *target = MDP_Y_CBCR_H2V2_P010;  break;
+  case kFormatYCbCr420TP10Ubwc:         *target = MDP_Y_CBCR_H2V2_TP10_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:
+  case kFormatRGBA1010102:
+  case kFormatARGB2101010:
+  case kFormatRGBX1010102:
+  case kFormatXRGB2101010:
+  case kFormatBGRA1010102:
+  case kFormatABGR2101010:
+  case kFormatBGRX1010102:
+  case kFormatXBGR2101010:
+  case kFormatRGBA1010102Ubwc:
+  case kFormatRGBX1010102Ubwc:
+    *target = width * 4;
+    break;
+  case kFormatRGB888:
+  case kFormatBGR888:
+    *target = width * 3;
+    break;
+  case kFormatRGB565:
+  case kFormatBGR565:
+  case kFormatBGR565Ubwc:
+    *target = width * 2;
+    break;
+  case kFormatYCbCr420SemiPlanarVenus:
+  case kFormatYCbCr420SPVenusUbwc:
+  case kFormatYCbCr420Planar:
+  case kFormatYCrCb420Planar:
+  case kFormatYCrCb420PlanarStride16:
+  case kFormatYCbCr420SemiPlanar:
+  case kFormatYCrCb420SemiPlanar:
+  case kFormatYCbCr420TP10Ubwc:
+    *target = width;
+    break;
+  case kFormatYCbCr422H2V1Packed:
+  case kFormatCbYCrY422H2V1Packed:
+  case kFormatYCrCb422H2V1SemiPlanar:
+  case kFormatYCrCb422H1V2SemiPlanar:
+  case kFormatYCbCr422H2V1SemiPlanar:
+  case kFormatYCbCr422H1V2SemiPlanar:
+  case kFormatYCbCr420P010:
+  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 kBlendingOpaque:         *target = BLEND_OP_OPAQUE;          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,
+                           bool async_cursor_updates, uint32_t *mdp_flags) {
+  const 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_camera) {
+    *mdp_flags |= MDP_LAYER_SECURE_CAMERA_SESSION;
+  } else if (input_buffer.flags.secure) {
+    *mdp_flags |= MDP_LAYER_SECURE_SESSION;
+  }
+
+  if (input_buffer.flags.secure_display) {
+    *mdp_flags |= MDP_LAYER_SECURE_DISPLAY_SESSION;
+  }
+
+  if (layer->flags.solid_fill) {
+    *mdp_flags |= MDP_LAYER_SOLID_FILL;
+  }
+
+  if (layer->flags.cursor && async_cursor_updates) {
+    // command mode panels does not support async position update
+    *mdp_flags |= MDP_LAYER_ASYNC;
+  }
+}
+
+int HWDevice::GetFBNodeIndex(HWDeviceType device_type) {
+  for (int i = 0; i < kFBNodeMax; i++) {
+    HWPanelInfo panel_info;
+    GetHWPanelInfoByNode(i, &panel_info);
+    switch (device_type) {
+    case kDevicePrimary:
+      if (panel_info.is_primary_panel) {
+        return i;
+      }
+      break;
+    case kDeviceHDMI:
+      if (panel_info.is_pluggable == true) {
+        if (IsFBNodeConnected(i)) {
+          return i;
+        }
+      }
+      break;
+    case kDeviceVirtual:
+      if (panel_info.port == kPortWriteBack) {
+        return i;
+      }
+      break;
+    default:
+      break;
+    }
+  }
+  return -1;
+}
+
+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, supported roi_count =%d, Dynamic FPS = %d",
+        hw_panel_info_.partial_update, hw_panel_info_.left_roi_count, hw_panel_info_.dynamic_fps);
+  DLOGI("Align: left = %d, width = %d, top = %d, height = %d",
+        hw_panel_info_.left_align, hw_panel_info_.width_align,
+        hw_panel_info_.top_align, hw_panel_info_.height_align);
+  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("Ping Pong Split = %d",  hw_panel_info_.ping_pong_split);
+  DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split,
+        hw_panel_info_.split_info.right_split);
+}
+
+void HWDevice::GetHWPanelNameByNode(int device_node, HWPanelInfo *panel_info) {
+  string file_name = fb_path_ + to_string(device_node) + "/msm_fb_panel_info";
+
+  Sys::fstream fs(file_name, fstream::in);
+  if (!fs.is_open()) {
+    DLOGW("Failed to open msm_fb_panel_info node device node %d", device_node);
+    return;
+  }
+
+  string line;
+  while (Sys::getline_(fs, line)) {
+    uint32_t token_count = 0;
+    const uint32_t max_count = 10;
+    char *tokens[max_count] = { NULL };
+    if (!ParseLine(line.c_str(), "=\n", tokens, max_count, &token_count)) {
+      if (!strncmp(tokens[0], "panel_name", strlen("panel_name"))) {
+        snprintf(panel_info->panel_name, sizeof(panel_info->panel_name), "%s", tokens[1]);
+        break;
+      }
+    }
+  }
+}
+
+void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) {
+  string file_name = fb_path_ + to_string(device_node) + "/msm_fb_panel_info";
+
+  Sys::fstream fs(file_name, fstream::in);
+  if (!fs.is_open()) {
+    DLOGW("Failed to open msm_fb_panel_info node device node %d", device_node);
+    return;
+  }
+
+  string line;
+  while (Sys::getline_(fs, line)) {
+    uint32_t token_count = 0;
+    const uint32_t max_count = 10;
+    char *tokens[max_count] = { NULL };
+    if (!ParseLine(line.c_str(), 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], "dfps_porch_mode", strlen("dfps_porch_mode"))) {
+        panel_info->dfps_porch_mode = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "is_pingpong_split", strlen("is_pingpong_split"))) {
+        panel_info->ping_pong_split = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
+        panel_info->min_fps = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
+        panel_info->max_fps = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "primary_panel", strlen("primary_panel"))) {
+        panel_info->is_primary_panel = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "is_pluggable", strlen("is_pluggable"))) {
+        panel_info->is_pluggable = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "pu_roi_cnt", strlen("pu_roi_cnt"))) {
+        panel_info->left_roi_count = UINT32(atoi(tokens[1]));
+        panel_info->right_roi_count = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "is_hdr_enabled", strlen("is_hdr_enabled"))) {
+        panel_info->hdr_enabled = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "peak_brightness", strlen("peak_brightness"))) {
+        panel_info->peak_luminance = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "average_brightness", strlen("average_brightness"))) {
+        panel_info->average_luminance = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "blackness_level", strlen("blackness_level"))) {
+        panel_info->blackness_level = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "white_chromaticity_x", strlen("white_chromaticity_x"))) {
+        panel_info->primaries.white_point[0] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "white_chromaticity_y", strlen("white_chromaticity_y"))) {
+        panel_info->primaries.white_point[1] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "red_chromaticity_x", strlen("red_chromaticity_x"))) {
+        panel_info->primaries.red[0] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "red_chromaticity_y", strlen("red_chromaticity_y"))) {
+        panel_info->primaries.red[1] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "green_chromaticity_x", strlen("green_chromaticity_x"))) {
+        panel_info->primaries.green[0] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "green_chromaticity_y", strlen("green_chromaticity_y"))) {
+        panel_info->primaries.green[1] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "blue_chromaticity_x", strlen("blue_chromaticity_x"))) {
+        panel_info->primaries.blue[0] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "blue_chromaticity_y", strlen("blue_chromaticity_y"))) {
+        panel_info->primaries.blue[1] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "panel_orientation", strlen("panel_orientation"))) {
+        int32_t panel_orient = atoi(tokens[1]);
+        panel_info->panel_orientation.flip_horizontal = ((panel_orient & MDP_FLIP_LR) > 0);
+        panel_info->panel_orientation.flip_vertical = ((panel_orient & MDP_FLIP_UD) > 0);
+        panel_info->panel_orientation.rotation = ((panel_orient & MDP_ROT_90) > 0);
+      }
+    }
+  }
+
+  GetHWDisplayPortAndMode(device_node, panel_info);
+  GetSplitInfo(device_node, panel_info);
+  GetHWPanelNameByNode(device_node, panel_info);
+  GetHWPanelMaxBrightnessFromNode(panel_info);
+}
+
+void HWDevice::GetHWDisplayPortAndMode(int device_node, HWPanelInfo *panel_info) {
+  DisplayPort *port = &panel_info->port;
+  HWDisplayMode *mode = &panel_info->mode;
+
+  *port = kPortDefault;
+  *mode = kModeDefault;
+
+  string file_name = fb_path_ + to_string(device_node) + "/msm_fb_type";
+
+  Sys::fstream fs(file_name, fstream::in);
+  if (!fs.is_open()) {
+    DLOGW("File not found %s", file_name.c_str());
+    return;
+  }
+
+  string line;
+  if (!Sys::getline_(fs, line)) {
+    return;
+  }
+
+  if ((strncmp(line.c_str(), "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
+    *port = kPortDSI;
+    *mode = kModeCommand;
+  } else if ((strncmp(line.c_str(), "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) {
+    *port = kPortDSI;
+    *mode = kModeVideo;
+  } else if ((strncmp(line.c_str(), "lvds panel", strlen("lvds panel")) == 0)) {
+    *port = kPortLVDS;
+    *mode = kModeVideo;
+  } else if ((strncmp(line.c_str(), "edp panel", strlen("edp panel")) == 0)) {
+    *port = kPortEDP;
+    *mode = kModeVideo;
+  } else if ((strncmp(line.c_str(), "dtv panel", strlen("dtv panel")) == 0)) {
+    *port = kPortDTV;
+    *mode = kModeVideo;
+  } else if ((strncmp(line.c_str(), "writeback panel", strlen("writeback panel")) == 0)) {
+    *port = kPortWriteBack;
+    *mode = kModeCommand;
+  } else if ((strncmp(line.c_str(), "dp panel", strlen("dp panel")) == 0)) {
+    *port = kPortDP;
+    *mode = kModeVideo;
+  }
+
+  return;
+}
+
+void HWDevice::GetSplitInfo(int device_node, HWPanelInfo *panel_info) {
+  // Split info - for MDSS Version 5 - No need to check version here
+  string file_name = fb_path_ + to_string(device_node) + "/msm_fb_split";
+
+  Sys::fstream fs(file_name, fstream::in);
+  if (!fs.is_open()) {
+    DLOGW("File not found %s", file_name.c_str());
+    return;
+  }
+
+  // Format "left right" space as delimiter
+  uint32_t token_count = 0;
+  const uint32_t max_count = 10;
+  char *tokens[max_count] = { NULL };
+  string line;
+  if (Sys::getline_(fs, line)) {
+    if (!ParseLine(line.c_str(), tokens, max_count, &token_count)) {
+      panel_info->split_info.left_split = UINT32(atoi(tokens[0]));
+      panel_info->split_info.right_split = UINT32(atoi(tokens[1]));
+    }
+  }
+}
+
+void HWDevice::GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info) {
+  char brightness[kMaxStringLength] = { 0 };
+  char kMaxBrightnessNode[64] = { 0 };
+
+  snprintf(kMaxBrightnessNode, sizeof(kMaxBrightnessNode), "%s",
+           "/sys/class/leds/lcd-backlight/max_brightness");
+
+  panel_info->panel_max_brightness = 0;
+  int fd = Sys::open_(kMaxBrightnessNode, O_RDONLY);
+  if (fd < 0) {
+    DLOGW("Failed to open max brightness node = %s, error = %s", kMaxBrightnessNode,
+          strerror(errno));
+    return;
+  }
+
+  if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
+    panel_info->panel_max_brightness = atoi(brightness);
+    DLOGI("Max brightness level = %d", panel_info->panel_max_brightness);
+  } else {
+    DLOGW("Failed to read max brightness level. error = %s", strerror(errno));
+  }
+  Sys::close_(fd);
+}
+
+int HWDevice::ParseLine(const 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(const_cast<char *>(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;
+}
+
+int HWDevice::ParseLine(const char *input, const char *delim, char *tokens[],
+                        const uint32_t max_token, uint32_t *count) {
+  char *tmp_token = NULL;
+  char *temp_ptr;
+  uint32_t index = 0;
+  if (!input) {
+    return -1;
+  }
+  tmp_token = strtok_r(const_cast<char *>(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) {
+  char hpdpath[kMaxStringLength];
+  const char *value = enable ? "1" : "0";
+
+  // Enable HPD for all pluggable devices.
+  for (int i = 0; i < kFBNodeMax; i++) {
+    HWPanelInfo panel_info;
+    GetHWPanelInfoByNode(i, &panel_info);
+    if (panel_info.is_pluggable == true) {
+      snprintf(hpdpath , sizeof(hpdpath), "%s%d/hpd", fb_path_, i);
+
+      ssize_t length = SysFsWrite(hpdpath, value, 1);
+      if (length <= 0) {
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
+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_));
+  mdp_out_layer_.buffer.fence = -1;
+  hw_scale_->ResetScaleParams();
+  memset(&pp_params_, 0, sizeof(pp_params_));
+  memset(&igc_lut_data_, 0, sizeof(igc_lut_data_));
+
+  for (size_t i = 0; i < mdp_dest_scalar_data_.size(); i++) {
+    mdp_dest_scalar_data_[i] = {};
+  }
+
+  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;
+  mdp_disp_commit_.commit_v1.dest_scaler = mdp_dest_scalar_data_.data();
+}
+
+void HWDevice::SetCSC(const ColorMetaData &color_metadata, mdp_color_space *color_space) {
+  switch (color_metadata.colorPrimaries) {
+  case ColorPrimaries_BT601_6_525:
+  case ColorPrimaries_BT601_6_625:
+    *color_space = ((color_metadata.range == Range_Full) ? MDP_CSC_ITU_R_601_FR :
+                                                           MDP_CSC_ITU_R_601);
+    break;
+  case ColorPrimaries_BT709_5:
+    *color_space = MDP_CSC_ITU_R_709;
+    break;
+#if defined MDP_CSC_ITU_R_2020 && defined MDP_CSC_ITU_R_2020_FR
+  case ColorPrimaries_BT2020:
+    *color_space = static_cast<mdp_color_space>((color_metadata.range == Range_Full) ?
+                                                 MDP_CSC_ITU_R_2020_FR : MDP_CSC_ITU_R_2020);
+    break;
+#endif
+  default:
+    break;
+  }
+}
+
+void HWDevice::SetIGC(const LayerBuffer *layer_buffer, uint32_t index) {
+  mdp_input_layer &mdp_layer = mdp_in_layers_[index];
+  mdp_overlay_pp_params &pp_params = pp_params_[index];
+  mdp_igc_lut_data_v1_7 &igc_lut_data = igc_lut_data_[index];
+
+  switch (layer_buffer->igc) {
+  case kIGCsRGB:
+    igc_lut_data.table_fmt = mdp_igc_srgb;
+    pp_params.igc_cfg.ops = MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE;
+    break;
+
+  default:
+    pp_params.igc_cfg.ops = MDP_PP_OPS_DISABLE;
+    break;
+  }
+
+  pp_params.config_ops = MDP_OVERLAY_PP_IGC_CFG;
+  pp_params.igc_cfg.version = mdp_igc_v1_7;
+  pp_params.igc_cfg.cfg_payload = &igc_lut_data;
+
+  mdp_layer.pp_info = &pp_params;
+  mdp_layer.flags |= MDP_LAYER_PP;
+}
+
+DisplayError HWDevice::SetCursorPosition(HWLayers *hw_layers, int x, int y) {
+  DTRACE_SCOPED();
+
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  uint32_t count = UINT32(hw_layer_info.hw_layers.size());
+  uint32_t cursor_index = count - 1;
+  HWPipeInfo *left_pipe = &hw_layers->config[cursor_index].left_pipe;
+
+  mdp_async_layer async_layer = {};
+  async_layer.flags = MDP_LAYER_ASYNC;
+  async_layer.pipe_ndx = left_pipe->pipe_id;
+  async_layer.src.x = UINT32(left_pipe->src_roi.left);
+  async_layer.src.y = UINT32(left_pipe->src_roi.top);
+  async_layer.dst.x = UINT32(x);
+  async_layer.dst.y = UINT32(y);
+
+  mdp_position_update pos_update = {};
+  pos_update.input_layer_cnt = 1;
+  pos_update.input_layers = &async_layer;
+  if (Sys::ioctl_(device_fd_, INT(MSMFB_ASYNC_POSITION_UPDATE), &pos_update) < 0) {
+    if (errno == ESHUTDOWN) {
+      DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+      return kErrorShutDown;
+    }
+    IOCTL_LOGE(MSMFB_ASYNC_POSITION_UPDATE, device_type_);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWDevice::GetPPFeaturesVersion(PPFeatureVersion *vers) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDevice::SetPPFeatures(PPFeaturesConfig *feature_list) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDevice::SetVSyncState(bool enable) {
+  int vsync_on = enable ? 1 : 0;
+  if (Sys::ioctl_(device_fd_, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) < 0) {
+    if (errno == ESHUTDOWN) {
+      DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+      return kErrorShutDown;
+    }
+    IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, device_type_);
+    return kErrorHardware;
+  }
+  return kErrorNone;
+}
+
+void HWDevice::SetIdleTimeoutMs(uint32_t timeout_ms) {
+}
+
+DisplayError HWDevice::SetDisplayMode(const HWDisplayMode hw_display_mode) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDevice::SetRefreshRate(uint32_t refresh_rate) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDevice::SetPanelBrightness(int level) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDevice::CachePanelBrightness(int level) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDevice::GetHWScanInfo(HWScanInfo *scan_info) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDevice::GetVideoFormat(uint32_t config_index, uint32_t *video_format) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDevice::GetMaxCEAFormat(uint32_t *max_cea_format) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDevice::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDevice::GetPanelBrightness(int *level) {
+  return kErrorNotSupported;
+}
+
+ssize_t HWDevice::SysFsWrite(const char* file_node, const char* value, ssize_t length) {
+  int fd = Sys::open_(file_node, O_RDWR, 0);
+  if (fd < 0) {
+    DLOGW("Open failed = %s", file_node);
+    return -1;
+  }
+  ssize_t len = Sys::pwrite_(fd, value, static_cast<size_t>(length), 0);
+  if (len <= 0) {
+    DLOGE("Write failed for path %s with value %s", file_node, value);
+  }
+  Sys::close_(fd);
+
+  return len;
+}
+
+bool HWDevice::IsFBNodeConnected(int fb_node) {
+  string file_name = fb_path_ + to_string(fb_node) + "/connected";
+
+  Sys::fstream fs(file_name, fstream::in);
+  if (!fs.is_open()) {
+    DLOGW("File not found %s", file_name.c_str());
+    return false;
+  }
+
+  string line;
+  if (!Sys::getline_(fs, line)) {
+    return false;
+  }
+
+  return atoi(line.c_str());
+}
+
+DisplayError HWDevice::SetS3DMode(HWS3DMode s3d_mode) {
+  return kErrorNotSupported;
+}
+
+DisplayError HWDevice::SetScaleLutConfig(HWScaleLutInfo *lut_info) {
+  mdp_scale_luts_info mdp_lut_info = {};
+  mdp_set_cfg cfg = {};
+
+  if (!hw_resource_.has_qseed3) {
+    DLOGV_IF(kTagDriverConfig, "No support for QSEED3 luts");
+    return kErrorNone;
+  }
+
+  if (!lut_info->dir_lut_size && !lut_info->dir_lut && !lut_info->cir_lut_size &&
+      !lut_info->cir_lut && !lut_info->sep_lut_size && !lut_info->sep_lut) {
+      // HWSupports QSEED3, but LutInfo is invalid as scalar is disabled by property or
+      // its loading failed. Driver will use default settings/filter
+      return kErrorNone;
+  }
+
+  mdp_lut_info.dir_lut_size = lut_info->dir_lut_size;
+  mdp_lut_info.dir_lut = lut_info->dir_lut;
+  mdp_lut_info.cir_lut_size = lut_info->cir_lut_size;
+  mdp_lut_info.cir_lut = lut_info->cir_lut;
+  mdp_lut_info.sep_lut_size = lut_info->sep_lut_size;
+  mdp_lut_info.sep_lut = lut_info->sep_lut;
+
+  cfg.flags = MDP_QSEED3_LUT_CFG;
+  cfg.len = sizeof(mdp_scale_luts_info);
+  cfg.payload = reinterpret_cast<uint64_t>(&mdp_lut_info);
+
+  if (Sys::ioctl_(device_fd_, MSMFB_MDP_SET_CFG, &cfg) < 0) {
+    if (errno == ESHUTDOWN) {
+      DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+      return kErrorShutDown;
+    }
+    IOCTL_LOGE(MSMFB_MDP_SET_CFG, device_type_);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWDevice::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+  if (!hw_resource_.hw_dest_scalar_info.count) {
+    return kErrorNotSupported;
+  }
+
+  if (mixer_attributes.width > display_attributes_.x_pixels ||
+      mixer_attributes.height > display_attributes_.y_pixels) {
+    DLOGW_IF(kTagDriverConfig, "Input resolution exceeds display resolution! input: res %dx%d "\
+             "display: res %dx%d", mixer_attributes.width, mixer_attributes.height,
+             display_attributes_.x_pixels, display_attributes_.y_pixels);
+    return kErrorNotSupported;
+  }
+
+  uint32_t max_input_width = hw_resource_.hw_dest_scalar_info.max_input_width;
+  if (display_attributes_.is_device_split) {
+    max_input_width *= 2;
+  }
+
+  if (mixer_attributes.width > max_input_width) {
+    DLOGW_IF(kTagDriverConfig, "Input width exceeds width limit! input_width %d width_limit %d",
+             mixer_attributes.width, max_input_width);
+    return kErrorNotSupported;
+  }
+
+  float mixer_aspect_ratio = FLOAT(mixer_attributes.width) / FLOAT(mixer_attributes.height);
+  float display_aspect_ratio =
+    FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels);
+
+  if (display_aspect_ratio != mixer_aspect_ratio) {
+    DLOGW_IF(kTagDriverConfig, "Aspect ratio mismatch! input: res %dx%d display: res %dx%d",
+             mixer_attributes.width, mixer_attributes.height, display_attributes_.x_pixels,
+             display_attributes_.y_pixels);
+    return kErrorNotSupported;
+  }
+
+  float scale_x = FLOAT(display_attributes_.x_pixels) / FLOAT(mixer_attributes.width);
+  float scale_y = FLOAT(display_attributes_.y_pixels) / FLOAT(mixer_attributes.height);
+  float max_scale_up = hw_resource_.hw_dest_scalar_info.max_scale_up;
+  if (scale_x > max_scale_up || scale_y > max_scale_up) {
+    DLOGW_IF(kTagDriverConfig, "Up scaling ratio exceeds for destination scalar upscale " \
+             "limit scale_x %f scale_y %f max_scale_up %f", scale_x, scale_y, max_scale_up);
+    return kErrorNotSupported;
+  }
+
+  float mixer_split_ratio = FLOAT(mixer_attributes_.split_left) / FLOAT(mixer_attributes_.width);
+
+  mixer_attributes_ = mixer_attributes;
+  mixer_attributes_.split_left = mixer_attributes_.width;
+  if (display_attributes_.is_device_split) {
+    mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWDevice::GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
+  if (!mixer_attributes) {
+    return kErrorParameters;
+  }
+
+  *mixer_attributes = mixer_attributes_;
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/core/fb/hw_device.h b/sdm845/sdm/libs/core/fb/hw_device.h
new file mode 100644
index 0000000..2eea87b
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_device.h
@@ -0,0 +1,167 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <linux/msm_mdp_ext.h>
+#include <linux/mdss_rotator.h>
+#include <pthread.h>
+#include <vector>
+
+#include "hw_interface.h"
+#include "hw_scale.h"
+
+#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, \
+                                      type, errno, strerror(errno))
+
+#ifndef MDP_LAYER_MULTIRECT_ENABLE
+#define MDP_LAYER_MULTIRECT_ENABLE 0
+#endif
+
+#ifndef MDP_LAYER_MULTIRECT_PARALLEL_MODE
+#define MDP_LAYER_MULTIRECT_PARALLEL_MODE 0
+#endif
+
+#ifndef MDP_LAYER_SECURE_CAMERA_SESSION
+#define MDP_LAYER_SECURE_CAMERA_SESSION 0
+#endif
+
+namespace sdm {
+class HWInfoInterface;
+
+class HWDevice : public HWInterface {
+ public:
+  virtual ~HWDevice() {}
+  virtual DisplayError Init();
+  virtual DisplayError Deinit();
+
+ protected:
+  explicit HWDevice(BufferSyncHandler *buffer_sync_handler);
+
+  // From HWInterface
+  virtual DisplayError GetActiveConfig(uint32_t *active_config);
+  virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+  virtual DisplayError GetDisplayAttributes(uint32_t index,
+                                            HWDisplayAttributes *display_attributes);
+  virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
+  virtual DisplayError SetDisplayAttributes(uint32_t index);
+  virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
+  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 DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
+  virtual DisplayError SetPPFeatures(PPFeaturesConfig *feature_list);
+  virtual DisplayError SetVSyncState(bool enable);
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+  virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+  virtual DisplayError SetPanelBrightness(int level);
+  virtual DisplayError CachePanelBrightness(int level);
+  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 SetCursorPosition(HWLayers *hw_layers, int x, int y);
+  virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
+  virtual DisplayError GetPanelBrightness(int *level);
+  virtual DisplayError SetAutoRefresh(bool enable) { return kErrorNone; }
+  virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
+  virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
+  virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
+  virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
+
+  enum {
+    kHWEventVSync,
+    kHWEventBlank,
+  };
+
+  static const int kMaxStringLength = 1024;
+  static const int kNumPhysicalDisplays = 2;
+  // This indicates the number of fb devices created in the driver for all interfaces. Any addition
+  // of new fb devices should be added here.
+  static const int kFBNodeMax = 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,
+                   bool async_cursor_updates, uint32_t *mdp_flags);
+  // 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);
+  void GetHWPanelNameByNode(int device_node, HWPanelInfo *panel_info);
+  void GetHWDisplayPortAndMode(int device_node, HWPanelInfo *panel_info);
+  void GetSplitInfo(int device_node, HWPanelInfo *panel_info);
+  void GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info);
+  int ParseLine(const char *input, char *tokens[], const uint32_t max_token, uint32_t *count);
+  int ParseLine(const char *input, const char *delim, char *tokens[],
+                const uint32_t max_token, uint32_t *count);
+  void ResetDisplayParams();
+  void SetCSC(const ColorMetaData &color_metadata, mdp_color_space *color_space);
+  void SetIGC(const LayerBuffer *layer_buffer, uint32_t index);
+
+  bool EnableHotPlugDetection(int enable);
+  ssize_t SysFsWrite(const char* file_node, const char* value, ssize_t length);
+  bool IsFBNodeConnected(int fb_node);
+
+  HWResourceInfo hw_resource_;
+  HWPanelInfo hw_panel_info_;
+  HWInfoInterface *hw_info_intf_;
+  int fb_node_index_;
+  const char *fb_path_;
+  BufferSyncHandler *buffer_sync_handler_;
+  int device_fd_ = -1;
+  int stored_retire_fence = -1;
+  HWDeviceType device_type_;
+  mdp_layer_commit mdp_disp_commit_;
+  mdp_input_layer mdp_in_layers_[kMaxSDELayers * 2];   // split panel (left + right)
+  HWScale *hw_scale_ = NULL;
+  mdp_overlay_pp_params pp_params_[kMaxSDELayers * 2];
+  mdp_igc_lut_data_v1_7 igc_lut_data_[kMaxSDELayers * 2];
+  mdp_output_layer mdp_out_layer_;
+  const char *device_name_;
+  bool synchronous_commit_;
+  HWDisplayAttributes display_attributes_ = {};
+  HWMixerAttributes mixer_attributes_ = {};
+  std::vector<mdp_destination_scaler_data> mdp_dest_scalar_data_;
+  int bl_level_update_commit = -1;
+  bool bl_update_commit = false;
+};
+
+}  // namespace sdm
+
+#endif  // __HW_DEVICE_H__
+
diff --git a/sdm845/sdm/libs/core/fb/hw_events.cpp b/sdm845/sdm/libs/core/fb/hw_events.cpp
new file mode 100644
index 0000000..c0467f9
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_events.cpp
@@ -0,0 +1,245 @@
+/*
+* Copyright (c) 2015 - 2017, 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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/prctl.h>
+#include <utils/debug.h>
+#include <utils/sys.h>
+#include <pthread.h>
+#include <algorithm>
+#include <vector>
+#include <map>
+#include <utility>
+
+#include "hw_events.h"
+
+#define __CLASS__ "HWEvents"
+
+namespace sdm {
+
+pollfd HWEvents::InitializePollFd(HWEventData *event_data) {
+  char node_path[kMaxStringLength] = {0};
+  char data[kMaxStringLength] = {0};
+  pollfd poll_fd = {0};
+  poll_fd.fd = -1;
+
+  if (event_data->event_type == HWEvent::EXIT) {
+    // Create an eventfd to be used to unblock the poll system call when
+    // a thread is exiting.
+    poll_fd.fd = Sys::eventfd_(0, 0);
+    poll_fd.events |= POLLIN;
+    exit_fd_ = poll_fd.fd;
+  } else {
+    snprintf(node_path, sizeof(node_path), "%s%d/%s", fb_path_, fb_num_,
+             map_event_to_node_[event_data->event_type]);
+    poll_fd.fd = Sys::open_(node_path, O_RDONLY);
+    poll_fd.events |= POLLPRI | POLLERR;
+  }
+
+  if (poll_fd.fd < 0) {
+    DLOGW("open failed for display=%d event=%s, error=%s", fb_num_,
+          map_event_to_node_[event_data->event_type], strerror(errno));
+    return poll_fd;
+  }
+
+  // Read once on all fds to clear data on all fds.
+  Sys::pread_(poll_fd.fd, data , kMaxStringLength, 0);
+
+  return poll_fd;
+}
+
+DisplayError HWEvents::SetEventParser(HWEvent event_type, HWEventData *event_data) {
+  DisplayError error = kErrorNone;
+  switch (event_type) {
+    case HWEvent::VSYNC:
+      event_data->event_parser = &HWEvents::HandleVSync;
+      break;
+    case HWEvent::IDLE_NOTIFY:
+      event_data->event_parser = &HWEvents::HandleIdleTimeout;
+      break;
+    case HWEvent::CEC_READ_MESSAGE:
+      event_data->event_parser = &HWEvents::HandleCECMessage;
+      break;
+    case HWEvent::EXIT:
+      event_data->event_parser = &HWEvents::HandleThreadExit;
+      break;
+    case HWEvent::SHOW_BLANK_EVENT:
+      event_data->event_parser = &HWEvents::HandleBlank;
+      break;
+    case HWEvent::THERMAL_LEVEL:
+      event_data->event_parser = &HWEvents::HandleThermal;
+      break;
+    case HWEvent::IDLE_POWER_COLLAPSE:
+      event_data->event_parser = &HWEvents::HandleIdlePowerCollapse;
+      break;
+    default:
+      error = kErrorParameters;
+      break;
+  }
+
+  return error;
+}
+
+void HWEvents::PopulateHWEventData() {
+  for (uint32_t i = 0; i < event_list_.size(); i++) {
+    HWEventData event_data;
+    event_data.event_type = event_list_[i];
+    SetEventParser(event_list_[i], &event_data);
+    poll_fds_[i] = InitializePollFd(&event_data);
+    event_data_list_.push_back(event_data);
+  }
+}
+
+DisplayError HWEvents::Init(int fb_num, HWEventHandler *event_handler,
+                            const vector<HWEvent> &event_list) {
+  if (!event_handler)
+    return kErrorParameters;
+
+  event_handler_ = event_handler;
+  fb_num_ = fb_num;
+  event_list_ = event_list;
+  poll_fds_.resize(event_list_.size());
+  event_thread_name_ += " - " + std::to_string(fb_num_);
+  map_event_to_node_ = {{HWEvent::VSYNC, "vsync_event"}, {HWEvent::EXIT, "thread_exit"},
+    {HWEvent::IDLE_NOTIFY, "idle_notify"}, {HWEvent::SHOW_BLANK_EVENT, "show_blank_event"},
+    {HWEvent::CEC_READ_MESSAGE, "cec/rd_msg"}, {HWEvent::THERMAL_LEVEL, "msm_fb_thermal_level"},
+    {HWEvent::IDLE_POWER_COLLAPSE, "idle_power_collapse"}};
+
+  PopulateHWEventData();
+
+  if (pthread_create(&event_thread_, NULL, &DisplayEventThread, this) < 0) {
+    DLOGE("Failed to start %s, error = %s", event_thread_name_.c_str());
+    return kErrorResources;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWEvents::Deinit() {
+  exit_threads_ = true;
+  Sys::pthread_cancel_(event_thread_);
+
+  uint64_t exit_value = 1;
+  ssize_t write_size = Sys::write_(exit_fd_, &exit_value, sizeof(uint64_t));
+  if (write_size != sizeof(uint64_t))
+    DLOGW("Error triggering exit_fd_ (%d). write size = %d, error = %s", exit_fd_, write_size,
+          strerror(errno));
+
+  pthread_join(event_thread_, NULL);
+
+  for (uint32_t i = 0; i < event_list_.size(); i++) {
+    Sys::close_(poll_fds_[i].fd);
+    poll_fds_[i].fd = -1;
+  }
+
+  return kErrorNone;
+}
+
+void* HWEvents::DisplayEventThread(void *context) {
+  if (context) {
+    return reinterpret_cast<HWEvents *>(context)->DisplayEventHandler();
+  }
+
+  return NULL;
+}
+
+void* HWEvents::DisplayEventHandler() {
+  char data[kMaxStringLength] = {0};
+
+  prctl(PR_SET_NAME, event_thread_name_.c_str(), 0, 0, 0);
+  setpriority(PRIO_PROCESS, 0, kThreadPriorityUrgent);
+
+  while (!exit_threads_) {
+    int error = Sys::poll_(poll_fds_.data(), UINT32(event_list_.size()), -1);
+
+    if (error <= 0) {
+      DLOGW("poll failed. error = %s", strerror(errno));
+      continue;
+    }
+
+    for (uint32_t event = 0; event < event_list_.size(); event++) {
+      pollfd &poll_fd = poll_fds_[event];
+
+      if (event_list_.at(event) == HWEvent::EXIT) {
+        if ((poll_fd.revents & POLLIN) && (Sys::read_(poll_fd.fd, data, kMaxStringLength) > 0)) {
+          (this->*(event_data_list_[event]).event_parser)(data);
+        }
+      } else {
+        if ((poll_fd.revents & POLLPRI) &&
+                (Sys::pread_(poll_fd.fd, data, kMaxStringLength, 0) > 0)) {
+          (this->*(event_data_list_[event]).event_parser)(data);
+        }
+      }
+    }
+  }
+
+  pthread_exit(0);
+
+  return NULL;
+}
+
+void HWEvents::HandleVSync(char *data) {
+  int64_t timestamp = 0;
+  if (!strncmp(data, "VSYNC=", strlen("VSYNC="))) {
+    timestamp = strtoll(data + strlen("VSYNC="), NULL, 0);
+  }
+
+  event_handler_->VSync(timestamp);
+}
+
+void HWEvents::HandleIdleTimeout(char *data) {
+  event_handler_->IdleTimeout();
+}
+
+void HWEvents::HandleThermal(char *data) {
+  int64_t thermal_level = 0;
+  if (!strncmp(data, "thermal_level=", strlen("thermal_level="))) {
+    thermal_level = strtoll(data + strlen("thermal_level="), NULL, 0);
+  }
+
+  DLOGI("Received thermal notification with thermal level = %d", thermal_level);
+
+  event_handler_->ThermalEvent(thermal_level);
+}
+
+void HWEvents::HandleCECMessage(char *data) {
+  event_handler_->CECMessage(data);
+}
+
+void HWEvents::HandleIdlePowerCollapse(char *data) {
+  event_handler_->IdlePowerCollapse();
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/fb/hw_events.h b/sdm845/sdm/libs/core/fb/hw_events.h
new file mode 100644
index 0000000..3d9cec8
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_events.h
@@ -0,0 +1,90 @@
+/*
+* Copyright (c) 2015 - 2017, 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_EVENTS_H__
+#define __HW_EVENTS_H__
+
+#include <sys/poll.h>
+#include <string>
+#include <vector>
+#include <map>
+#include <utility>
+
+#include "hw_interface.h"
+#include "hw_events_interface.h"
+
+namespace sdm {
+
+using std::vector;
+using std::map;
+
+class HWEvents : public HWEventsInterface {
+ public:
+  virtual DisplayError Init(int fb_num, HWEventHandler *event_handler,
+                            const vector<HWEvent> &event_list);
+  virtual DisplayError Deinit();
+  virtual DisplayError SetEventState(HWEvent event, bool enable, void *aux = nullptr) {
+    return kErrorNotSupported;
+  }
+
+ private:
+  static const int kMaxStringLength = 1024;
+
+  typedef void (HWEvents::*EventParser)(char *);
+
+  struct HWEventData {
+    HWEvent event_type {};
+    EventParser event_parser {};
+  };
+
+  static void* DisplayEventThread(void *context);
+  void* DisplayEventHandler();
+  void HandleVSync(char *data);
+  void HandleBlank(char *data) { }
+  void HandleIdleTimeout(char *data);
+  void HandleThermal(char *data);
+  void HandleCECMessage(char *data);
+  void HandleThreadExit(char *data) { }
+  void HandleIdlePowerCollapse(char *data);
+  void PopulateHWEventData();
+  DisplayError SetEventParser(HWEvent event_type, HWEventData *event_data);
+  pollfd InitializePollFd(HWEventData *event_data);
+
+  HWEventHandler *event_handler_ = {};
+  vector<HWEvent> event_list_ = {};
+  vector<HWEventData> event_data_list_ = {};
+  vector<pollfd> poll_fds_ = {};
+  map<HWEvent, const char *> map_event_to_node_ = {};
+  pthread_t event_thread_ = {};
+  std::string event_thread_name_ = "SDM_EventThread";
+  bool exit_threads_ = false;
+  const char* fb_path_ = "/sys/devices/virtual/graphics/fb";
+  int fb_num_ = -1;
+  int exit_fd_ = -1;
+};
+
+}  // namespace sdm
+
+#endif  // __HW_EVENTS_H__
+
diff --git a/sdm845/sdm/libs/core/fb/hw_hdmi.cpp b/sdm845/sdm/libs/core/fb/hw_hdmi.cpp
new file mode 100644
index 0000000..334a043
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_hdmi.cpp
@@ -0,0 +1,1064 @@
+/*
+* Copyright (c) 2015 - 2017, 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 <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <linux/videodev2.h>
+#include <utils/debug.h>
+#include <utils/sys.h>
+#include <utils/formats.h>
+
+#include <vector>
+#include <map>
+#include <utility>
+
+#include "hw_hdmi.h"
+
+#define __CLASS__ "HWHDMI"
+
+namespace sdm {
+
+#ifdef MDP_HDR_STREAM
+static int32_t GetEOTF(const GammaTransfer &transfer) {
+  int32_t mdp_transfer = -1;
+
+  switch (transfer) {
+  case Transfer_SMPTE_ST2084:
+    mdp_transfer = MDP_HDR_EOTF_SMTPE_ST2084;
+    break;
+  case Transfer_HLG:
+    mdp_transfer = MDP_HDR_EOTF_HLG;
+    break;
+  default:
+    DLOGW("Unknown Transfer: %d", transfer);
+  }
+
+  return mdp_transfer;
+}
+
+static int32_t GetColoriMetry(const LayerBuffer & layer_buffer) {
+  bool is_yuv = layer_buffer.flags.video;
+  int32_t colorimetry = -1;
+
+  if (is_yuv) {
+    switch (layer_buffer.color_metadata.colorPrimaries) {
+    case ColorPrimaries_BT601_6_525:
+    case ColorPrimaries_BT601_6_625:
+      colorimetry = MDP_COLORIMETRY_YCBCR_ITU_R_BT_601;
+      break;
+    case ColorPrimaries_BT709_5:
+      colorimetry = MDP_COLORIMETRY_YCBCR_ITU_R_BT_709;
+      break;
+    case ColorPrimaries_BT2020:
+      colorimetry = MDP_COLORIMETRY_YCBCR_ITU_R_BT_2020_YCBCR;
+      break;
+    default:
+      DLOGW("Unknown color primary = %d for YUV", layer_buffer.color_metadata.colorPrimaries);
+    }
+  }
+
+  return colorimetry;
+}
+
+static int32_t GetPixelEncoding(const LayerBuffer &layer_buffer) {
+  bool is_yuv = layer_buffer.flags.video;
+  int32_t mdp_pixel_encoding = -1;
+  mdp_pixel_encoding = MDP_PIXEL_ENCODING_RGB;  // set RGB as default
+
+  if (is_yuv) {
+    switch (layer_buffer.format) {
+    case kFormatYCbCr420SemiPlanarVenus:
+    case kFormatYCbCr420SPVenusUbwc:
+    case kFormatYCbCr420Planar:
+    case kFormatYCrCb420Planar:
+    case kFormatYCrCb420PlanarStride16:
+    case kFormatYCbCr420SemiPlanar:
+    case kFormatYCrCb420SemiPlanar:
+    case kFormatYCbCr420P010:
+    case kFormatYCbCr420TP10Ubwc:
+      mdp_pixel_encoding = MDP_PIXEL_ENCODING_YCBCR_420;
+      break;
+    case kFormatYCbCr422H2V1Packed:
+    case kFormatYCrCb422H2V1SemiPlanar:
+    case kFormatYCrCb422H1V2SemiPlanar:
+    case kFormatYCbCr422H2V1SemiPlanar:
+    case kFormatYCbCr422H1V2SemiPlanar:
+      mdp_pixel_encoding = MDP_PIXEL_ENCODING_YCBCR_422;
+      break;
+    default:  // other yuv formats
+      DLOGW("New YUV format = %d, need to add support", layer_buffer.format);
+      break;
+    }
+  }
+
+  return mdp_pixel_encoding;
+}
+static int32_t GetBitsPerComponent(const LayerBuffer &layer_buffer) {
+  bool is_yuv = layer_buffer.flags.video;
+  bool is_10_bit = Is10BitFormat(layer_buffer.format);
+  int32_t mdp_bpc = -1;
+
+  if (is_yuv) {
+    mdp_bpc = is_10_bit ? MDP_YUV_10_BPC : MDP_YUV_8_BPC;
+  } else {
+    mdp_bpc = is_10_bit ? MDP_RGB_10_BPC : MDP_RGB_8_BPC;
+  }
+
+  return mdp_bpc;
+}
+
+static uint32_t GetRange(const ColorRange &range) {
+  return ((range == Range_Full) ? MDP_DYNAMIC_RANGE_VESA : MDP_DYNAMIC_RANGE_CEA);
+}
+
+static uint32_t GetContentType(const LayerBuffer &layer_buffer) {
+  return (layer_buffer.flags.video ? MDP_CONTENT_TYPE_VIDEO : MDP_CONTENT_TYPE_GRAPHICS);
+}
+#endif
+
+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;
+
+  info->grayscale = V4L2_PIX_FMT_RGB24;
+  // If the mode supports YUV420 set grayscale to the FOURCC value for YUV420.
+  std::bitset<32> pixel_formats = mode->pixel_formats;
+  if (pixel_formats[1]) {
+    info->grayscale = V4L2_PIX_FMT_NV12;
+  }
+
+  return true;
+}
+
+HWHDMI::HWHDMI(BufferSyncHandler *buffer_sync_handler,  HWInfoInterface *hw_info_intf)
+  : HWDevice(buffer_sync_handler), hw_scan_info_(), active_config_index_(0) {
+  HWDevice::device_type_ = kDeviceHDMI;
+  HWDevice::device_name_ = "HDMI Display Device";
+  HWDevice::hw_info_intf_ = hw_info_intf;
+}
+
+DisplayError HWHDMI::Init() {
+  DisplayError error = kErrorNone;
+
+  SetSourceProductInformation("vendor_name", "ro.product.manufacturer");
+  SetSourceProductInformation("product_description", "ro.product.name");
+
+  error = HWDevice::Init();
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  mdp_dest_scalar_data_.resize(hw_resource_.hw_dest_scalar_info.count);
+
+  error = ReadEDIDInfo();
+  if (error != kErrorNone) {
+    Deinit();
+    return error;
+  }
+
+  if (!IsResolutionFilePresent()) {
+    Deinit();
+    return kErrorHardware;
+  }
+
+  error = ReadTimingInfo();
+  if (error != kErrorNone) {
+    Deinit();
+    return error;
+  }
+
+  ReadScanInfo();
+
+  GetPanelS3DMode();
+
+  s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+                             (kS3DModeNone, HDMI_S3D_NONE));
+  s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+                             (kS3DModeLR, HDMI_S3D_SIDE_BY_SIDE));
+  s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+                             (kS3DModeRL, HDMI_S3D_SIDE_BY_SIDE));
+  s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+                             (kS3DModeTB, HDMI_S3D_TOP_AND_BOTTOM));
+  s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
+                             (kS3DModeFP, HDMI_S3D_FRAME_PACKING));
+
+  return error;
+}
+
+DisplayError HWHDMI::GetNumDisplayAttributes(uint32_t *count) {
+  *count = UINT32(hdmi_modes_.size());
+  if (*count <= 0) {
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::GetActiveConfig(uint32_t *active_config_index) {
+  *active_config_index = active_config_index_;
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::ReadEDIDInfo() {
+  ssize_t length = -1;
+  char edid_str[kPageSize] = {'\0'};
+  char edid_path[kMaxStringLength] = {'\0'};
+  snprintf(edid_path, sizeof(edid_path), "%s%d/edid_modes", fb_path_, fb_node_index_);
+  int edid_file = Sys::open_(edid_path, O_RDONLY);
+  if (edid_file < 0) {
+    DLOGE("EDID file open failed.");
+    return kErrorHardware;
+  }
+
+  length = Sys::pread_(edid_file, edid_str, sizeof(edid_str)-1, 0);
+  if (length <= 0) {
+    DLOGE("%s: edid_modes file empty");
+    return kErrorHardware;
+  }
+  Sys::close_(edid_file);
+
+  DLOGI("EDID mode string: %s", edid_str);
+  while (length > 1 && isspace(edid_str[length-1])) {
+    --length;
+  }
+  edid_str[length] = '\0';
+
+  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 };
+    uint32_t hdmi_mode_count = 0;
+
+    ParseLine(ptr, tokens, edid_count_max, &hdmi_mode_count);
+
+    supported_video_modes_.resize(hdmi_mode_count);
+
+    hdmi_modes_.resize(hdmi_mode_count);
+    for (uint32_t i = 0; i < hdmi_mode_count; i++) {
+      hdmi_modes_[i] = UINT32(atoi(tokens[i]));
+    }
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::GetDisplayAttributes(uint32_t index,
+                                          HWDisplayAttributes *display_attributes) {
+  DTRACE_SCOPED();
+
+  if (index >= hdmi_modes_.size()) {
+    return kErrorNotSupported;
+  }
+
+  // Get the resolution info from the look up table
+  msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[0];
+  for (uint32_t i = 0; i < hdmi_modes_.size(); 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_front_porch = timing_mode->front_porch_v;
+  display_attributes->v_back_porch = timing_mode->back_porch_v;
+  display_attributes->v_pulse_width = 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->is_device_split = false;
+  if (display_attributes->x_pixels > hw_resource_.max_mixer_width) {
+    display_attributes->is_device_split = true;
+    display_attributes->h_total += h_blanking;
+  }
+
+  GetDisplayS3DSupport(index, display_attributes);
+  std::bitset<32> pixel_formats = timing_mode->pixel_formats;
+
+  display_attributes->is_yuv = pixel_formats[1];
+
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::SetDisplayAttributes(uint32_t index) {
+  DTRACE_SCOPED();
+
+  if (index > hdmi_modes_.size()) {
+    return kErrorNotSupported;
+  }
+
+  // Variable screen info
+  fb_var_screeninfo vscreeninfo = {};
+  if (Sys::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 (uint32_t i = 0; i < hdmi_modes_.size(); 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;
+  }
+
+  msmfb_metadata metadata = {};
+  metadata.op = metadata_op_vic;
+  metadata.data.video_info_code = timing_mode->video_format;
+  if (Sys::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 (Sys::ioctl_(device_fd_, FBIOPUT_VSCREENINFO, &vscreeninfo) < 0) {
+    IOCTL_LOGE(FBIOPUT_VSCREENINFO, device_type_);
+    return kErrorHardware;
+  }
+
+  active_config_index_ = index;
+
+  frame_rate_ = timing_mode->refresh_rate;
+
+  // Get the display attributes for current active config index
+  GetDisplayAttributes(active_config_index_, &display_attributes_);
+  UpdateMixerAttributes();
+
+  supported_s3d_modes_.clear();
+  supported_s3d_modes_.push_back(kS3DModeNone);
+  for (uint32_t mode = kS3DModeNone + 1; mode < kS3DModeMax; mode ++) {
+    if (display_attributes_.s3d_config[(HWS3DMode)mode]) {
+      supported_s3d_modes_.push_back((HWS3DMode)mode);
+    }
+  }
+
+  SetS3DMode(kS3DModeNone);
+
+  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_modes_.size(); 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::Validate(HWLayers *hw_layers) {
+  HWDevice::ResetDisplayParams();
+  return HWDevice::Validate(hw_layers);
+}
+
+DisplayError HWHDMI::Commit(HWLayers *hw_layers) {
+  DisplayError error = UpdateHDRMetaData(hw_layers);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return HWDevice::Commit(hw_layers);
+}
+
+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) {
+  if (config_index > hdmi_modes_.size()) {
+    return kErrorNotSupported;
+  }
+
+  *video_format = hdmi_modes_[config_index];
+
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::GetMaxCEAFormat(uint32_t *max_cea_format) {
+  *max_cea_format = HDMI_VFRMT_END;
+
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
+  DisplayError error = kErrorNone;
+  int fd = -1;
+  char data[kMaxStringLength] = {'\0'};
+
+  snprintf(data, sizeof(data), "%s%d/hdcp2p2/min_level_change", fb_path_, fb_node_index_);
+
+  fd = Sys::open_(data, O_WRONLY);
+  if (fd < 0) {
+    DLOGW("File '%s' could not be opened.", data);
+    return kErrorHardware;
+  }
+
+  snprintf(data, sizeof(data), "%d", min_enc_level);
+
+  ssize_t err = Sys::pwrite_(fd, data, strlen(data), 0);
+  if (err <= 0) {
+    DLOGE("Write failed, Error = %s", strerror(errno));
+    error = kErrorHardware;
+  }
+
+  Sys::close_(fd);
+
+  return error;
+}
+
+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[kPageSize] = {'\0'};
+
+  snprintf(data, sizeof(data), "%s%d/scan_info", fb_path_, fb_node_index_);
+  scan_info_file = Sys::open_(data, O_RDONLY);
+  if (scan_info_file < 0) {
+    DLOGW("File '%s' not found.", data);
+    return;
+  }
+
+  memset(&data[0], 0, sizeof(data));
+  len = Sys::pread_(scan_info_file, data, sizeof(data) - 1, 0);
+  if (len <= 0) {
+    Sys::close_(scan_info_file);
+    DLOGW("File %s%d/scan_info is empty.", fb_path_, fb_node_index_);
+    return;
+  }
+  data[len] = '\0';
+  Sys::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(UINT32(atoi(tokens[0])));
+  hw_scan_info_.it_scan_support = MapHWScanSupport(UINT32(atoi(tokens[1])));
+  hw_scan_info_.cea_scan_support = MapHWScanSupport(UINT32(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);
+}
+
+int HWHDMI::OpenResolutionFile(int file_mode) {
+  char file_path[kMaxStringLength];
+  memset(file_path, 0, sizeof(file_path));
+  snprintf(file_path , sizeof(file_path), "%s%d/res_info", fb_path_, fb_node_index_);
+
+  int fd = Sys::open_(file_path, file_mode);
+
+  if (fd < 0) {
+    DLOGE("file '%s' not found : ret = %d err str: %s", file_path, fd, strerror(errno));
+  }
+
+  return fd;
+}
+
+// Method to request HDMI driver to write a new page of timing info into res_info node
+void HWHDMI::RequestNewPage(uint32_t page_number) {
+  char page_string[kPageSize];
+  int fd = OpenResolutionFile(O_WRONLY);
+  if (fd < 0) {
+    return;
+  }
+
+  snprintf(page_string, sizeof(page_string), "%d", page_number);
+
+  DLOGI_IF(kTagDriverConfig, "page=%s", page_string);
+
+  ssize_t err = Sys::pwrite_(fd, page_string, sizeof(page_string), 0);
+  if (err <= 0) {
+    DLOGE("Write to res_info failed (%s)", strerror(errno));
+  }
+
+  Sys::close_(fd);
+}
+
+// Reads the contents of res_info node into a buffer if the file is not empty
+bool HWHDMI::ReadResolutionFile(char *config_buffer) {
+  ssize_t bytes_read = 0;
+  int fd = OpenResolutionFile(O_RDONLY);
+  if (fd >= 0) {
+    bytes_read = Sys::pread_(fd, config_buffer, kPageSize, 0);
+    Sys::close_(fd);
+  }
+
+  DLOGI_IF(kTagDriverConfig, "bytes_read = %d", bytes_read);
+
+  return (bytes_read > 0);
+}
+
+// Populates the internal timing info structure with the timing info obtained
+// from the HDMI driver
+DisplayError HWHDMI::ReadTimingInfo() {
+  uint32_t config_index = 0;
+  uint32_t page_number = MSM_HDMI_INIT_RES_PAGE;
+  uint32_t size = sizeof(msm_hdmi_mode_timing_info);
+
+  while (true) {
+    char config_buffer[kPageSize] = {0};
+    msm_hdmi_mode_timing_info *info = reinterpret_cast<msm_hdmi_mode_timing_info *>(config_buffer);
+    RequestNewPage(page_number);
+
+    if (!ReadResolutionFile(config_buffer)) {
+      break;
+    }
+
+    while (info->video_format && size < kPageSize && config_index < hdmi_modes_.size()) {
+      supported_video_modes_[config_index] = *info;
+      size += sizeof(msm_hdmi_mode_timing_info);
+
+      DLOGI_IF(kTagDriverConfig, "Config=%d Mode %d: (%dx%d) @ %d, pixel formats %d",
+               config_index,
+               supported_video_modes_[config_index].video_format,
+               supported_video_modes_[config_index].active_h,
+               supported_video_modes_[config_index].active_v,
+               supported_video_modes_[config_index].refresh_rate,
+               supported_video_modes_[config_index].pixel_formats);
+
+      info++;
+      config_index++;
+    }
+
+    size = sizeof(msm_hdmi_mode_timing_info);
+    // Request HDMI driver to populate res_info with more
+    // timing information
+    page_number++;
+  }
+
+  if (page_number == MSM_HDMI_INIT_RES_PAGE || config_index == 0) {
+    DLOGE("No timing information found.");
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+bool HWHDMI::IsResolutionFilePresent() {
+  bool is_file_present = false;
+  int fd = OpenResolutionFile(O_RDONLY);
+  if (fd >= 0) {
+    is_file_present = true;
+    Sys::close_(fd);
+  }
+
+  return is_file_present;
+}
+
+void HWHDMI::SetSourceProductInformation(const char *node, const char *name) {
+  char property_value[kMaxStringLength];
+  char sys_fs_path[kMaxStringLength];
+  int hdmi_node_index = GetFBNodeIndex(kDeviceHDMI);
+  if (hdmi_node_index < 0) {
+    return;
+  }
+
+  ssize_t length = 0;
+  bool prop_read_success = Debug::GetProperty(name, property_value);
+  if (!prop_read_success) {
+    return;
+  }
+
+  snprintf(sys_fs_path , sizeof(sys_fs_path), "%s%d/%s", fb_path_, hdmi_node_index, node);
+  length = HWDevice::SysFsWrite(sys_fs_path, property_value,
+                                static_cast<ssize_t>(strlen(property_value)));
+  if (length <= 0) {
+    DLOGW("Failed to write %s = %s", node, property_value);
+  }
+}
+
+DisplayError HWHDMI::GetDisplayS3DSupport(uint32_t index,
+                                          HWDisplayAttributes *attrib) {
+  ssize_t length = -1;
+  char edid_s3d_str[kPageSize] = {'\0'};
+  char edid_s3d_path[kMaxStringLength] = {'\0'};
+  snprintf(edid_s3d_path, sizeof(edid_s3d_path), "%s%d/edid_3d_modes", fb_path_, fb_node_index_);
+
+  if (index > hdmi_modes_.size()) {
+    return kErrorNotSupported;
+  }
+
+  attrib->s3d_config[kS3DModeNone] = 1;
+
+  // Three level inception!
+  // The string looks like 16=SSH,4=FP:TAB:SSH,5=FP:SSH,32=FP:TAB:SSH
+  // Initialize all the pointers to NULL to avoid crash in function strtok_r()
+  char *saveptr_l1 = NULL, *saveptr_l2 = NULL, *saveptr_l3 = NULL;
+  char *l1 = NULL, *l2 = NULL, *l3 = NULL;
+
+  int edid_s3d_node = Sys::open_(edid_s3d_path, O_RDONLY);
+  if (edid_s3d_node < 0) {
+    DLOGW("%s could not be opened : %s", edid_s3d_path, strerror(errno));
+    return kErrorNotSupported;
+  }
+
+  length = Sys::pread_(edid_s3d_node, edid_s3d_str, sizeof(edid_s3d_str)-1, 0);
+  if (length <= 0) {
+    Sys::close_(edid_s3d_node);
+    return kErrorNotSupported;
+  }
+
+  l1 = strtok_r(edid_s3d_str, ",", &saveptr_l1);
+  while (l1 != NULL) {
+    l2 = strtok_r(l1, "=", &saveptr_l2);
+    if (l2 != NULL) {
+      if (hdmi_modes_[index] == (uint32_t)atoi(l2)) {
+          l3 = strtok_r(saveptr_l2, ":", &saveptr_l3);
+          while (l3 != NULL) {
+            if (strncmp("SSH", l3, strlen("SSH")) == 0) {
+              attrib->s3d_config[kS3DModeLR] = 1;
+              attrib->s3d_config[kS3DModeRL] = 1;
+            } else if (strncmp("TAB", l3, strlen("TAB")) == 0) {
+              attrib->s3d_config[kS3DModeTB] = 1;
+            } else if (strncmp("FP", l3, strlen("FP")) == 0) {
+              attrib->s3d_config[kS3DModeFP] = 1;
+            }
+            l3 = strtok_r(NULL, ":", &saveptr_l3);
+          }
+      }
+    }
+    l1 = strtok_r(NULL, ",", &saveptr_l1);
+  }
+
+  Sys::close_(edid_s3d_node);
+  return kErrorNone;
+}
+
+bool HWHDMI::IsSupportedS3DMode(HWS3DMode s3d_mode) {
+  for (uint32_t i = 0; i < supported_s3d_modes_.size(); i++) {
+    if (supported_s3d_modes_[i] == s3d_mode) {
+      return true;
+    }
+  }
+  return false;
+}
+
+DisplayError HWHDMI::SetS3DMode(HWS3DMode s3d_mode) {
+  if (!IsSupportedS3DMode(s3d_mode)) {
+    DLOGW("S3D mode is not supported s3d_mode = %d", s3d_mode);
+    return kErrorNotSupported;
+  }
+
+  std::map<HWS3DMode, msm_hdmi_s3d_mode>::iterator it = s3d_mode_sdm_to_mdp_.find(s3d_mode);
+  if (it == s3d_mode_sdm_to_mdp_.end()) {
+    return kErrorNotSupported;
+  }
+  msm_hdmi_s3d_mode s3d_mdp_mode = it->second;
+
+  if (active_mdp_s3d_mode_ == s3d_mdp_mode) {
+    // HDMI_S3D_SIDE_BY_SIDE is an mdp mapping for kS3DModeLR and kS3DModeRL s3d modes. So no need
+    // to update the s3d_mode node. hw_panel_info needs to be updated to differentiate these two s3d
+    // modes in strategy
+    hw_panel_info_.s3d_mode = s3d_mode;
+    return kErrorNone;
+  }
+
+  ssize_t length = -1;
+  char s3d_mode_path[kMaxStringLength] = {'\0'};
+  char s3d_mode_string[kMaxStringLength] = {'\0'};
+  snprintf(s3d_mode_path, sizeof(s3d_mode_path), "%s%d/s3d_mode", fb_path_, fb_node_index_);
+
+  int s3d_mode_node = Sys::open_(s3d_mode_path, O_RDWR);
+  if (s3d_mode_node < 0) {
+    DLOGW("%s could not be opened : %s", s3d_mode_path, strerror(errno));
+    return kErrorNotSupported;
+  }
+
+  snprintf(s3d_mode_string, sizeof(s3d_mode_string), "%d", s3d_mdp_mode);
+  length = Sys::pwrite_(s3d_mode_node, s3d_mode_string, sizeof(s3d_mode_string), 0);
+  if (length <= 0) {
+    DLOGW("Failed to write into s3d node: %s", strerror(errno));
+    Sys::close_(s3d_mode_node);
+    return kErrorNotSupported;
+  }
+
+  active_mdp_s3d_mode_ = s3d_mdp_mode;
+  hw_panel_info_.s3d_mode = s3d_mode;
+  Sys::close_(s3d_mode_node);
+
+  DLOGI_IF(kTagDriverConfig, "Set s3d mode %d", hw_panel_info_.s3d_mode);
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::GetPanelS3DMode() {
+  ssize_t length = -1;
+  char s3d_mode_path[kMaxStringLength] = {'\0'};
+  char s3d_mode_string[kMaxStringLength] = {'\0'};
+  snprintf(s3d_mode_path, sizeof(s3d_mode_path), "%s%d/s3d_mode", fb_path_, fb_node_index_);
+  int panel_s3d_mode = 0;
+
+  int s3d_mode_node = Sys::open_(s3d_mode_path, O_RDWR);
+  if (s3d_mode_node < 0) {
+    DLOGE("%s could not be opened : %s", s3d_mode_path, strerror(errno));
+    return kErrorNotSupported;
+  }
+
+  length = Sys::pread_(s3d_mode_node, s3d_mode_string, sizeof(s3d_mode_string), 0);
+  if (length <= 0) {
+    DLOGE("Failed read s3d node: %s", strerror(errno));
+    Sys::close_(s3d_mode_node);
+    return kErrorNotSupported;
+  }
+
+  panel_s3d_mode = atoi(s3d_mode_string);
+  if (panel_s3d_mode < HDMI_S3D_NONE || panel_s3d_mode >= HDMI_S3D_MAX) {
+    Sys::close_(s3d_mode_node);
+    DLOGW("HDMI panel S3D mode is not supported panel_s3d_mode = %d", panel_s3d_mode);
+    return kErrorUndefined;
+  }
+
+  active_mdp_s3d_mode_  = static_cast<msm_hdmi_s3d_mode>(panel_s3d_mode);
+  Sys::close_(s3d_mode_node);
+
+  DLOGI_IF(kTagDriverConfig, "Get HDMI panel s3d mode %d", active_mdp_s3d_mode_);
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::GetDynamicFrameRateMode(uint32_t refresh_rate, uint32_t *mode,
+                                             DynamicFPSData *data, uint32_t *config_index) {
+  msm_hdmi_mode_timing_info *cur = NULL;
+  msm_hdmi_mode_timing_info *dst = NULL;
+  uint32_t i = 0;
+  int pre_refresh_rate_diff = 0;
+  bool pre_unstd_mode = false;
+
+  for (i = 0; i < hdmi_modes_.size(); i++) {
+    msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[i];
+    if (timing_mode->video_format == hdmi_modes_[active_config_index_]) {
+      cur = timing_mode;
+      break;
+    }
+  }
+
+  if (cur == NULL) {
+    DLOGE("can't find timing info for active config index(%d)", active_config_index_);
+    return kErrorUndefined;
+  }
+
+  if (cur->refresh_rate != frame_rate_) {
+    pre_unstd_mode = true;
+  }
+
+  if (i >= hdmi_modes_.size()) {
+    return kErrorNotSupported;
+  }
+
+  dst = cur;
+  pre_refresh_rate_diff = static_cast<int>(dst->refresh_rate) - static_cast<int>(refresh_rate);
+
+  for (i = 0; i < hdmi_modes_.size(); i++) {
+    msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[i];
+    if (cur->active_h == timing_mode->active_h &&
+       cur->active_v == timing_mode->active_v &&
+       cur->pixel_formats == timing_mode->pixel_formats ) {
+      int cur_refresh_rate_diff = static_cast<int>(timing_mode->refresh_rate) -
+                                  static_cast<int>(refresh_rate);
+      if (abs(pre_refresh_rate_diff) > abs(cur_refresh_rate_diff)) {
+        pre_refresh_rate_diff = cur_refresh_rate_diff;
+        dst = timing_mode;
+      }
+    }
+  }
+
+  if (pre_refresh_rate_diff > kThresholdRefreshRate) {
+    return kErrorNotSupported;
+  }
+
+  GetConfigIndex(dst->video_format, config_index);
+
+  data->hor_front_porch = dst->front_porch_h;
+  data->hor_back_porch = dst->back_porch_h;
+  data->hor_pulse_width = dst->pulse_width_h;
+  data->clk_rate_hz = dst->pixel_freq;
+  data->fps = refresh_rate;
+
+  if (dst->front_porch_h != cur->front_porch_h) {
+    *mode = kModeHFP;
+  }
+
+  if (dst->refresh_rate != refresh_rate || dst->pixel_freq != cur->pixel_freq) {
+    if (*mode == kModeHFP) {
+      if (dst->refresh_rate != refresh_rate) {
+        *mode = kModeHFPCalcClock;
+      } else {
+        *mode = kModeClockHFP;
+      }
+    } else {
+        *mode = kModeClock;
+    }
+  }
+
+  if (pre_unstd_mode && (*mode == kModeHFP)) {
+    *mode = kModeClockHFP;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::SetRefreshRate(uint32_t refresh_rate) {
+  char mode_path[kMaxStringLength] = {0};
+  char node_path[kMaxStringLength] = {0};
+  uint32_t mode = kModeClock;
+  uint32_t config_index = 0;
+  DynamicFPSData data;
+  DisplayError error = kErrorNone;
+
+  if (refresh_rate == frame_rate_) {
+    return error;
+  }
+
+  error = GetDynamicFrameRateMode(refresh_rate, &mode, &data, &config_index);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  snprintf(mode_path, sizeof(mode_path), "%s%d/msm_fb_dfps_mode", fb_path_, fb_node_index_);
+  snprintf(node_path, sizeof(node_path), "%s%d/dynamic_fps", fb_path_, fb_node_index_);
+
+  int fd_mode = Sys::open_(mode_path, O_WRONLY);
+  if (fd_mode < 0) {
+    DLOGE("Failed to open %s with error %s", mode_path, strerror(errno));
+    return kErrorFileDescriptor;
+  }
+
+  char dfps_mode[kMaxStringLength];
+  snprintf(dfps_mode, sizeof(dfps_mode), "%d", mode);
+  DLOGI_IF(kTagDriverConfig, "Setting dfps_mode  = %d", mode);
+  ssize_t len = Sys::pwrite_(fd_mode, dfps_mode, strlen(dfps_mode), 0);
+  if (len < 0) {
+    DLOGE("Failed to enable dfps mode %d with error %s", mode, strerror(errno));
+    Sys::close_(fd_mode);
+    return kErrorUndefined;
+  }
+  Sys::close_(fd_mode);
+
+  int fd_node = Sys::open_(node_path, O_WRONLY);
+  if (fd_node < 0) {
+    DLOGE("Failed to open %s with error %s", node_path, strerror(errno));
+    return kErrorFileDescriptor;
+  }
+
+  char refresh_rate_string[kMaxStringLength];
+  if (mode == kModeHFP || mode == kModeClock) {
+    snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", data.fps);
+    DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", data.fps);
+  } else {
+    snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d %d %d %d %d",
+             data.hor_front_porch, data.hor_back_porch, data.hor_pulse_width,
+             data.clk_rate_hz, data.fps);
+  }
+  len = Sys::pwrite_(fd_node, refresh_rate_string, strlen(refresh_rate_string), 0);
+  if (len < 0) {
+    DLOGE("Failed to write %d with error %s", refresh_rate, strerror(errno));
+    Sys::close_(fd_node);
+    return kErrorUndefined;
+  }
+  Sys::close_(fd_node);
+
+  error = ReadTimingInfo();
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  GetDisplayAttributes(config_index, &display_attributes_);
+  UpdateMixerAttributes();
+
+  frame_rate_ = refresh_rate;
+  active_config_index_ = config_index;
+
+  DLOGI_IF(kTagDriverConfig, "config_index(%d) Mode(%d) frame_rate(%d)",
+           config_index,
+           mode,
+           frame_rate_);
+
+  return kErrorNone;
+}
+
+void HWHDMI::UpdateMixerAttributes() {
+  mixer_attributes_.width = display_attributes_.x_pixels;
+  mixer_attributes_.height = display_attributes_.y_pixels;
+  mixer_attributes_.split_left = display_attributes_.is_device_split ?
+      (display_attributes_.x_pixels / 2) : mixer_attributes_.width;
+}
+
+DisplayError HWHDMI::UpdateHDRMetaData(HWLayers *hw_layers) {
+  const HWHDRLayerInfo &hdr_layer_info = hw_layers->info.hdr_layer_info;
+  if (!hw_panel_info_.hdr_enabled || hdr_layer_info.operation == HWHDRLayerInfo::kNoOp) {
+    return kErrorNone;
+  }
+
+  DisplayError error = kErrorNone;
+
+#ifdef MDP_HDR_STREAM
+  char hdr_stream_path[kMaxStringLength] = {};
+  snprintf(hdr_stream_path, sizeof(hdr_stream_path), "%s%d/hdr_stream", fb_path_, fb_node_index_);
+
+  int fd = Sys::open_(hdr_stream_path, O_WRONLY);
+  if (fd < 0) {
+    DLOGE("Failed to open %s with error %s", hdr_stream_path, strerror(errno));
+    return kErrorFileDescriptor;
+  }
+
+  Layer hdr_layer = {};
+  if (hdr_layer_info.operation == HWHDRLayerInfo::kSet && hdr_layer_info.layer_index > -1) {
+    hdr_layer = *(hw_layers->info.stack->layers.at(UINT32(hdr_layer_info.layer_index)));
+  }
+
+  const LayerBuffer *layer_buffer = &hdr_layer.input_buffer;
+  const MasteringDisplay &mastering_display = layer_buffer->color_metadata.masteringDisplayInfo;
+  const ContentLightLevel &light_level = layer_buffer->color_metadata.contentLightLevel;
+  const Primaries &primaries = mastering_display.primaries;
+
+  mdp_hdr_stream hdr_stream = {};
+  if (hdr_layer_info.operation == HWHDRLayerInfo::kSet) {
+    int32_t eotf = GetEOTF(layer_buffer->color_metadata.transfer);
+    hdr_stream.eotf = (eotf < 0) ? 0 : UINT32(eotf);
+    hdr_stream.white_point_x = primaries.whitePoint[0];
+    hdr_stream.white_point_y = primaries.whitePoint[1];
+    hdr_stream.display_primaries_x[0] = primaries.rgbPrimaries[0][0];
+    hdr_stream.display_primaries_y[0] = primaries.rgbPrimaries[0][1];
+    hdr_stream.display_primaries_x[1] = primaries.rgbPrimaries[1][0];
+    hdr_stream.display_primaries_y[1] = primaries.rgbPrimaries[1][1];
+    hdr_stream.display_primaries_x[2] = primaries.rgbPrimaries[2][0];
+    hdr_stream.display_primaries_y[2] = primaries.rgbPrimaries[2][1];
+    hdr_stream.min_luminance = mastering_display.minDisplayLuminance;
+    hdr_stream.max_luminance = mastering_display.maxDisplayLuminance/10000;
+    hdr_stream.max_content_light_level = light_level.maxContentLightLevel;
+    hdr_stream.max_average_light_level = light_level.minPicAverageLightLevel;
+    // DP related
+    int32_t pixel_encoding = GetPixelEncoding(hdr_layer.input_buffer);
+    hdr_stream.pixel_encoding = (pixel_encoding < 0) ? 0 : UINT32(pixel_encoding);
+    int32_t colorimetry = GetColoriMetry(hdr_layer.input_buffer);
+    hdr_stream.colorimetry = (colorimetry < 0) ? 0 : UINT32(colorimetry);
+    hdr_stream.range = GetRange(hdr_layer.input_buffer.color_metadata.range);
+    int32_t bits_per_component = GetBitsPerComponent(hdr_layer.input_buffer);
+    hdr_stream.bits_per_component = (bits_per_component  < 0) ? 0 : UINT32(bits_per_component);
+    hdr_stream.content_type = GetContentType(hdr_layer.input_buffer);
+
+    DLOGV_IF(kTagDriverConfig, "HDR Stream : MaxDisplayLuminance = %d MinDisplayLuminance = %d\n"
+      "MaxContentLightLevel = %d MaxAverageLightLevel = %d Red_x = %d Red_y = %d Green_x = %d\n"
+      "Green_y = %d Blue_x = %d Blue_y = %d WhitePoint_x = %d WhitePoint_y = %d EOTF = %d\n"
+      "PixelEncoding = %d Colorimetry = %d Range = %d BPC = %d ContentType = %d",
+      hdr_stream.max_luminance, hdr_stream.min_luminance, hdr_stream.max_content_light_level,
+      hdr_stream.max_average_light_level, hdr_stream.display_primaries_x[0],
+      hdr_stream.display_primaries_y[0], hdr_stream.display_primaries_x[1],
+      hdr_stream.display_primaries_y[1], hdr_stream.display_primaries_x[2],
+      hdr_stream.display_primaries_y[2], hdr_stream.white_point_x, hdr_stream.white_point_x,
+      hdr_stream.eotf, hdr_stream.pixel_encoding, hdr_stream.colorimetry, hdr_stream.range,
+      hdr_stream.bits_per_component, hdr_stream.content_type);
+  }
+
+  const void *hdr_metadata = reinterpret_cast<const void*>(&hdr_stream);
+  ssize_t len = Sys::pwrite_(fd, hdr_metadata, sizeof(hdr_stream), 0);
+  if (len <= 0) {
+    DLOGE("Failed to write hdr_metadata");
+    error = kErrorUndefined;
+  }
+  Sys::close_(fd);
+#endif
+
+  return error;
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/core/fb/hw_hdmi.h b/sdm845/sdm/libs/core/fb/hw_hdmi.h
new file mode 100644
index 0000000..625782e
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_hdmi.h
@@ -0,0 +1,126 @@
+/*
+* Copyright (c) 2015 - 2017, 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 <map>
+#include <vector>
+
+#include "hw_device.h"
+
+namespace sdm {
+
+using std::vector;
+
+class HWHDMI : public HWDevice {
+ public:
+  HWHDMI(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
+
+ protected:
+  enum HWFramerateUpdate {
+    // Switch framerate by switch to other standard modes though panel blank/unblank
+    kModeSuspendResume,
+    // Switch framerate by tuning pixel clock
+    kModeClock,
+    // Switch framerate by tuning vertical front porch
+    kModeVFP,
+    // Switch framerate by tuning horizontal front porch
+    kModeHFP,
+    // Switch framerate by tuning horizontal front porch and clock
+    kModeClockHFP,
+    // Switch framerate by tuning horizontal front porch and re-caculate clock
+    kModeHFPCalcClock,
+    kModeMAX
+  };
+
+  /**
+   * struct DynamicFPSData - defines dynamic fps related data
+   * @hor_front_porch: horizontal front porch
+   * @hor_back_porch: horizontal back porch
+   * @hor_pulse_width: horizontal pulse width
+   * @clk_rate_hz: panel clock rate in HZ
+   * @fps: frames per second
+   */
+  struct DynamicFPSData {
+    uint32_t hor_front_porch;
+    uint32_t hor_back_porch;
+    uint32_t hor_pulse_width;
+    uint32_t clk_rate_hz;
+    uint32_t fps;
+  };
+
+  virtual DisplayError Init();
+  virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+  // Requirement to call this only after the first config has been explicitly set by client
+  virtual DisplayError GetActiveConfig(uint32_t *active_config);
+  virtual DisplayError GetDisplayAttributes(uint32_t index,
+                                            HWDisplayAttributes *display_attributes);
+  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 OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
+  virtual DisplayError SetDisplayAttributes(uint32_t index);
+  virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+  virtual DisplayError Validate(HWLayers *hw_layers);
+  virtual DisplayError Commit(HWLayers *hw_layers);
+  virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+
+ private:
+  DisplayError ReadEDIDInfo();
+  void ReadScanInfo();
+  HWScanSupport MapHWScanSupport(uint32_t value);
+  int OpenResolutionFile(int file_mode);
+  void RequestNewPage(uint32_t page_number);
+  DisplayError ReadTimingInfo();
+  bool ReadResolutionFile(char *config_buffer);
+  bool IsResolutionFilePresent();
+  void SetSourceProductInformation(const char *node, const char *name);
+  DisplayError GetDisplayS3DSupport(uint32_t index,
+                                    HWDisplayAttributes *attrib);
+  DisplayError GetPanelS3DMode();
+  bool IsSupportedS3DMode(HWS3DMode s3d_mode);
+  void UpdateMixerAttributes();
+  DisplayError UpdateHDRMetaData(HWLayers *hw_layers);
+
+  DisplayError GetDynamicFrameRateMode(uint32_t refresh_rate, uint32_t*mode,
+                                       DynamicFPSData *data, uint32_t *config_index);
+  static const int kThresholdRefreshRate = 1000;
+  vector<uint32_t> hdmi_modes_;
+  // Holds the hdmi timing information. Ex: resolution, fps etc.,
+  vector<msm_hdmi_mode_timing_info> supported_video_modes_;
+  HWScanInfo hw_scan_info_;
+  uint32_t active_config_index_;
+  std::map<HWS3DMode, msm_hdmi_s3d_mode> s3d_mode_sdm_to_mdp_;
+  vector<HWS3DMode> supported_s3d_modes_;
+  msm_hdmi_s3d_mode active_mdp_s3d_mode_ = HDMI_S3D_NONE;
+  uint32_t frame_rate_ = 0;
+};
+
+}  // namespace sdm
+
+#endif  // __HW_HDMI_H__
+
diff --git a/sdm845/sdm/libs/core/fb/hw_info.cpp b/sdm845/sdm/libs/core/fb/hw_info.cpp
new file mode 100644
index 0000000..f2a13e3
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_info.cpp
@@ -0,0 +1,558 @@
+/*
+* Copyright (c) 2015-2017, 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 <string.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>
+#include <utils/sys.h>
+#include <dlfcn.h>
+
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "hw_info.h"
+
+#define __CLASS__ "HWInfo"
+
+using std::vector;
+using std::map;
+using std::string;
+using std::fstream;
+using std::to_string;
+
+namespace sdm {
+
+// kDefaultFormatSupport contains the bit map of supported formats for each hw blocks.
+// For eg: if Cursor supports MDP_RGBA_8888[bit-13] and MDP_RGB_565[bit-0], then cursor pipe array
+// contains { 0x01[0-3], 0x00[4-7], 0x00[8-12], 0x01[13-16], 0x00[17-20], 0x00[21-24], 0x00[24-28] }
+const std::bitset<8> HWInfo::kDefaultFormatSupport[kHWSubBlockMax][
+                                                      BITS_TO_BYTES(MDP_IMGTYPE_LIMIT1)] = {
+  { 0xFF, 0xF5, 0x1C, 0x1E, 0x20, 0xFF, 0x01, 0x00, 0xFE, 0x1F },  // kHWVIGPipe
+  { 0x33, 0xE0, 0x00, 0x16, 0x00, 0xBF, 0x00, 0x00, 0xFE, 0x07 },  // kHWRGBPipe
+  { 0x33, 0xE0, 0x00, 0x16, 0x00, 0xBF, 0x00, 0x00, 0xFE, 0x07 },  // kHWDMAPipe
+  { 0x12, 0x60, 0x0C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00 },  // kHWCursorPipe
+  { 0xFF, 0xF5, 0x1C, 0x1E, 0x20, 0xFF, 0x01, 0x00, 0xFE, 0x1F },  // kHWRotatorInput
+  { 0xFF, 0xF5, 0x1C, 0x1E, 0x20, 0xFF, 0x01, 0x00, 0xFE, 0x1F },  // kHWRotatorOutput
+  { 0x3F, 0xF4, 0x10, 0x1E, 0x20, 0xFF, 0x01, 0x00, 0xAA, 0x16 },  // kHWWBIntfOutput
+};
+
+int HWInfo::ParseString(const char *input, char *tokens[], const uint32_t max_token,
+                        const char *delim, uint32_t *count) {
+  char *tmp_token = NULL;
+  char *temp_ptr;
+  uint32_t index = 0;
+  if (!input) {
+    return -1;
+  }
+  tmp_token = strtok_r(const_cast<char *>(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 HWInfo::GetDynamicBWLimits(HWResourceInfo *hw_resource) {
+  Sys::fstream fs(kBWModeBitmap, fstream::in);
+  if (!fs.is_open()) {
+    DLOGE("File '%s' not found", kBWModeBitmap);
+    return kErrorHardware;
+  }
+
+  HWDynBwLimitInfo* bw_info = &hw_resource->dyn_bw_info;
+  for (int index = 0; index < kBwModeMax; index++) {
+    bw_info->total_bw_limit[index] = hw_resource->max_bandwidth_low;
+    bw_info->pipe_bw_limit[index] = hw_resource->max_pipe_bw;
+  }
+
+  uint32_t token_count = 0;
+  const uint32_t max_count = kBwModeMax;
+  char *tokens[max_count] = { NULL };
+  string line;
+  while (Sys::getline_(fs, line)) {
+    if (!ParseString(line.c_str(), tokens, max_count, ":, =\n", &token_count)) {
+      if (!strncmp(tokens[0], "default_pipe", strlen("default_pipe"))) {
+        bw_info->pipe_bw_limit[kBwDefault] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "camera_pipe", strlen("camera_pipe"))) {
+        bw_info->pipe_bw_limit[kBwCamera] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "vflip_pipe", strlen("vflip_pipe"))) {
+        bw_info->pipe_bw_limit[kBwVFlip] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "hflip_pipe", strlen("hflip_pipe"))) {
+        bw_info->pipe_bw_limit[kBwHFlip] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "default", strlen("default"))) {
+        bw_info->total_bw_limit[kBwDefault] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "camera", strlen("camera"))) {
+        bw_info->total_bw_limit[kBwCamera] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "vflip", strlen("vflip"))) {
+        bw_info->total_bw_limit[kBwVFlip] = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "hflip", strlen("hflip"))) {
+        bw_info->total_bw_limit[kBwHFlip] = UINT32(atoi(tokens[1]));
+      }
+    }
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWInfo::GetHWResourceInfo(HWResourceInfo *hw_resource) {
+  if (hw_resource_) {
+    *hw_resource = *hw_resource_;
+    return kErrorNone;
+  }
+  string fb_path = "/sys/devices/virtual/graphics/fb"
+                      + to_string(kHWCapabilitiesNode) + "/mdp/caps";
+
+  Sys::fstream fs(fb_path, fstream::in);
+  if (!fs.is_open()) {
+    DLOGE("File '%s' not found", fb_path.c_str());
+    return kErrorHardware;
+  }
+
+  hw_resource_ = new HWResourceInfo;
+
+  InitSupportedFormatMap(hw_resource_);
+  hw_resource_->hw_version = kHWMdssVersion5;
+
+  uint32_t token_count = 0;
+  const uint32_t max_count = 256;
+  char *tokens[max_count] = { NULL };
+  string line;
+  while (Sys::getline_(fs, line)) {
+    // parse the line and update information accordingly
+    if (!ParseString(line.c_str(), tokens, max_count, ":, =\n", &token_count)) {
+      if (!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
+        hw_resource_->hw_revision = UINT32(atoi(tokens[1]));  // HW Rev, v1/v2
+      } else if (!strncmp(tokens[0], "rot_input_fmts", strlen("rot_input_fmts"))) {
+        ParseFormats(&tokens[1], (token_count - 1), kHWRotatorInput, hw_resource_);
+      } else if (!strncmp(tokens[0], "rot_output_fmts", strlen("rot_output_fmts"))) {
+        ParseFormats(&tokens[1], (token_count - 1), kHWRotatorOutput, hw_resource_);
+      } else if (!strncmp(tokens[0], "wb_output_fmts", strlen("wb_output_fmts"))) {
+        ParseFormats(&tokens[1], (token_count - 1), kHWWBIntfOutput, hw_resource_);
+      } 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 = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "max_upscale_ratio", strlen("max_upscale_ratio"))) {
+        hw_resource_->max_scale_up = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "max_bandwidth_low", strlen("max_bandwidth_low"))) {
+        hw_resource_->max_bandwidth_low = std::stoull(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_bandwidth_high", strlen("max_bandwidth_high"))) {
+        hw_resource_->max_bandwidth_high = std::stoull(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_mixer_width", strlen("max_mixer_width"))) {
+        hw_resource_->max_mixer_width = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "max_pipe_width", strlen("max_pipe_width"))) {
+        hw_resource_->max_pipe_width = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "max_cursor_size", strlen("max_cursor_size"))) {
+        hw_resource_->max_cursor_size = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "max_pipe_bw", strlen("max_pipe_bw"))) {
+        hw_resource_->max_pipe_bw = std::stoull(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_mdp_clk", strlen("max_mdp_clk"))) {
+        hw_resource_->max_sde_clk = UINT32(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], "fmt_mt_nv12_factor", strlen("fmt_mt_nv12_factor"))) {
+        hw_resource_->macrotile_nv12_factor = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "fmt_mt_factor", strlen("fmt_mt_factor"))) {
+        hw_resource_->macrotile_factor = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "fmt_linear_factor", strlen("fmt_linear_factor"))) {
+        hw_resource_->linear_factor = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "scale_factor", strlen("scale_factor"))) {
+        hw_resource_->scale_factor = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "xtra_ff_factor", strlen("xtra_ff_factor"))) {
+        hw_resource_->extra_fudge_factor = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "amortizable_threshold", strlen("amortizable_threshold"))) {
+        hw_resource_->amortizable_threshold = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "system_overhead_lines", strlen("system_overhead_lines"))) {
+        hw_resource_->system_overhead_lines = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "wb_intf_index", strlen("wb_intf_index"))) {
+        hw_resource_->writeback_index = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "dest_scaler_count", strlen("dest_scaler_count"))) {
+        hw_resource_->hw_dest_scalar_info.count = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "max_dest_scale_up", strlen("max_dest_scale_up"))) {
+        hw_resource_->hw_dest_scalar_info.max_scale_up = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "max_dest_scaler_input_width",
+                 strlen("max_dest_scaler_input_width"))) {
+        hw_resource_->hw_dest_scalar_info.max_input_width = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "max_dest_scaler_output_width",
+                 strlen("max_dest_scaler_output_width"))) {
+        hw_resource_->hw_dest_scalar_info.max_output_width = UINT32(atoi(tokens[1]));
+      } 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], "ubwc", strlen("ubwc"))) {
+            hw_resource_->has_ubwc = 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], "dynamic_bw_limit", strlen("dynamic_bw_limit"))) {
+            hw_resource_->has_dyn_bw_support = true;
+          } else if (!strncmp(tokens[i], "separate_rotator", strlen("separate_rotator"))) {
+            hw_resource_->separate_rotator = true;
+          } else if (!strncmp(tokens[i], "qseed3", strlen("qseed3"))) {
+            hw_resource_->has_qseed3 = true;
+          } else if (!strncmp(tokens[i], "has_ppp", strlen("has_ppp"))) {
+            hw_resource_->has_ppp = true;
+          } else if (!strncmp(tokens[i], "concurrent_writeback", strlen("concurrent_writeback"))) {
+            hw_resource_->has_concurrent_writeback = true;
+          } else if (!strncmp(tokens[i], "avr", strlen("avr"))) {
+            hw_resource_->has_avr = true;
+          } else if (!strncmp(tokens[i], "hdr", strlen("hdr"))) {
+            hw_resource_->has_hdr = true;
+          }
+        }
+      } else if (!strncmp(tokens[0], "pipe_count", strlen("pipe_count"))) {
+        uint32_t pipe_count = UINT8(atoi(tokens[1]));
+        for (uint32_t i = 0; i < pipe_count; i++) {
+          Sys::getline_(fs, line);
+          if (!ParseString(line.c_str(), tokens, max_count, ": =\n", &token_count)) {
+            HWPipeCaps pipe_caps;
+            pipe_caps.type = kPipeTypeUnused;
+            for (uint32_t j = 0; j < token_count; j += 2) {
+              if (!strncmp(tokens[j], "pipe_type", strlen("pipe_type"))) {
+                if (!strncmp(tokens[j+1], "vig", strlen("vig"))) {
+                  pipe_caps.type = kPipeTypeVIG;
+                  hw_resource_->num_vig_pipe++;
+                } else if (!strncmp(tokens[j+1], "rgb", strlen("rgb"))) {
+                  pipe_caps.type = kPipeTypeRGB;
+                  hw_resource_->num_rgb_pipe++;
+                } else if (!strncmp(tokens[j+1], "dma", strlen("dma"))) {
+                  pipe_caps.type = kPipeTypeDMA;
+                  hw_resource_->num_dma_pipe++;
+                } else if (!strncmp(tokens[j+1], "cursor", strlen("cursor"))) {
+                  pipe_caps.type = kPipeTypeCursor;
+                  hw_resource_->num_cursor_pipe++;
+                }
+              } else if (!strncmp(tokens[j], "pipe_ndx", strlen("pipe_ndx"))) {
+                pipe_caps.id = UINT32(atoi(tokens[j+1]));
+              } else if (!strncmp(tokens[j], "rects", strlen("rects"))) {
+                pipe_caps.max_rects = UINT32(atoi(tokens[j+1]));
+              } else if (!strncmp(tokens[j], "fmts_supported", strlen("fmts_supported"))) {
+                char *tokens_fmt[max_count] = { NULL };
+                uint32_t token_fmt_count = 0;
+                if (!ParseString(tokens[j+1], tokens_fmt, max_count, ",\n", &token_fmt_count)) {
+                  if (pipe_caps.type == kPipeTypeVIG) {
+                    ParseFormats(tokens_fmt, token_fmt_count, kHWVIGPipe, hw_resource_);
+                  } else if (pipe_caps.type == kPipeTypeRGB) {
+                    ParseFormats(tokens_fmt, token_fmt_count, kHWRGBPipe, hw_resource_);
+                  } else if (pipe_caps.type == kPipeTypeDMA) {
+                    ParseFormats(tokens_fmt, token_fmt_count, kHWDMAPipe, hw_resource_);
+                  } else if (pipe_caps.type == kPipeTypeCursor) {
+                    ParseFormats(tokens_fmt, token_fmt_count, kHWCursorPipe, hw_resource_);
+                  }
+                }
+              }
+            }
+            hw_resource_->hw_pipes.push_back(pipe_caps);
+          }
+        }
+      }
+    }
+  }
+
+  // Disable destination scalar count to 0 if extension library is not present
+  DynLib extension_lib;
+  if (!extension_lib.Open("libsdmextension.so")) {
+    hw_resource_->hw_dest_scalar_info.count = 0;
+  }
+
+  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("SourceSplit = %d QSEED3 = %d", hw_resource_->is_src_split, hw_resource_->has_qseed3);
+  DLOGI("BWC = %d, UBWC = %d, Decimation = %d, Tile Format = %d Concurrent Writeback = %d",
+        hw_resource_->has_bwc, hw_resource_->has_ubwc, hw_resource_->has_decimation,
+        hw_resource_->has_macrotile, hw_resource_->has_concurrent_writeback);
+  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);
+  DLOGI("Prefill factors: Tiled_NV12 = %d, Tiled = %d, Linear = %d, Scale = %d, Fudge_factor = %d",
+        hw_resource_->macrotile_nv12_factor, hw_resource_->macrotile_factor,
+        hw_resource_->linear_factor, hw_resource_->scale_factor, hw_resource_->extra_fudge_factor);
+
+  if (hw_resource_->separate_rotator || hw_resource_->num_dma_pipe) {
+    GetHWRotatorInfo(hw_resource_);
+  }
+
+  // If the driver doesn't spell out the wb index, assume it to be the number of rotators,
+  // based on legacy implementation.
+  if (hw_resource_->writeback_index == kHWBlockMax) {
+    hw_resource_->writeback_index = hw_resource_->hw_rot_info.num_rotator;
+  }
+
+  if (hw_resource_->has_dyn_bw_support) {
+    DisplayError ret = GetDynamicBWLimits(hw_resource_);
+    if (ret != kErrorNone) {
+      DLOGE("Failed to read dynamic band width info");
+      return ret;
+    }
+
+    DLOGI("Has Support for multiple bw limits shown below");
+    for (int index = 0; index < kBwModeMax; index++) {
+      DLOGI("Mode-index=%d  total_bw_limit=%d and pipe_bw_limit=%d",
+            index, hw_resource_->dyn_bw_info.total_bw_limit[index],
+            hw_resource_->dyn_bw_info.pipe_bw_limit[index]);
+    }
+  }
+
+  *hw_resource = *hw_resource_;
+
+  return kErrorNone;
+}
+
+DisplayError HWInfo::GetHWRotatorInfo(HWResourceInfo *hw_resource) {
+  if (GetMDSSRotatorInfo(hw_resource) != kErrorNone)
+    return GetV4L2RotatorInfo(hw_resource);
+
+  return kErrorNone;
+}
+
+DisplayError HWInfo::GetMDSSRotatorInfo(HWResourceInfo *hw_resource) {
+  Sys::fstream fs(kRotatorCapsPath, fstream::in);
+  if (!fs.is_open()) {
+    DLOGW("File '%s' not found", kRotatorCapsPath);
+    return kErrorNotSupported;
+  }
+
+  uint32_t token_count = 0;
+  const uint32_t max_count = 10;
+  char *tokens[max_count] = { NULL };
+  string line;
+
+  hw_resource->hw_rot_info.type = HWRotatorInfo::ROT_TYPE_MDSS;
+  while (Sys::getline_(fs, line)) {
+    if (!ParseString(line.c_str(), tokens, max_count, ":, =\n", &token_count)) {
+      if (!strncmp(tokens[0], "wb_count", strlen("wb_count"))) {
+        hw_resource->hw_rot_info.num_rotator = UINT8(atoi(tokens[1]));
+        hw_resource->hw_rot_info.device_path = "/dev/mdss_rotator";
+      } else if (!strncmp(tokens[0], "downscale", strlen("downscale"))) {
+        hw_resource->hw_rot_info.has_downscale = UINT8(atoi(tokens[1]));
+      }
+    }
+  }
+
+  DLOGI("MDSS Rotator: Count = %d, Downscale = %d, Min_downscale = %f",
+        hw_resource->hw_rot_info.num_rotator, hw_resource->hw_rot_info.has_downscale,
+        hw_resource->hw_rot_info.min_downscale);
+
+  return kErrorNone;
+}
+
+DisplayError HWInfo::GetV4L2RotatorInfo(HWResourceInfo *hw_resource) {
+  string v4l2_path = "/sys/class/video4linux/video";
+  const uint32_t kMaxV4L2Nodes = 64;
+  bool found = false;
+
+  for (uint32_t i = 0; (i < kMaxV4L2Nodes) && (false == found); i++) {
+    string path = v4l2_path + to_string(i) + "/name";
+    Sys::fstream fs(path, fstream::in);
+    if (!fs.is_open()) {
+      continue;
+    }
+
+    string line;
+    if (Sys::getline_(fs, line) &&
+        (!strncmp(line.c_str(), "sde_rotator", strlen("sde_rotator")))) {
+       hw_resource->hw_rot_info.device_path = string("/dev/video" + to_string(i));
+       hw_resource->hw_rot_info.num_rotator++;
+       hw_resource->hw_rot_info.type = HWRotatorInfo::ROT_TYPE_V4L2;
+       hw_resource->hw_rot_info.has_downscale = true;
+
+       string caps_path = v4l2_path + to_string(i) + "/device/caps";
+       Sys::fstream caps_fs(caps_path, fstream::in);
+
+       if (caps_fs.is_open()) {
+         uint32_t token_count = 0;
+         const uint32_t max_count = 10;
+         char *tokens[max_count] = { NULL };
+         string caps;
+         while (Sys::getline_(caps_fs, caps)) {
+           if (!ParseString(caps.c_str(), tokens, max_count, ":, =\n", &token_count)) {
+             if (!strncmp(tokens[0], "downscale_compression", strlen("downscale_compression"))) {
+               hw_resource->hw_rot_info.downscale_compression = UINT8(atoi(tokens[1]));
+             } else if (!strncmp(tokens[0], "min_downscale", strlen("min_downscale"))) {
+               hw_resource->hw_rot_info.min_downscale = FLOAT(atof(tokens[1]));
+             }
+           }
+         }
+       }
+
+       // We support only 1 rotator
+       found = true;
+    }
+  }
+
+  DLOGI("V4L2 Rotator: Count = %d, Downscale = %d, Min_downscale = %f, Downscale_compression = %d",
+        hw_resource->hw_rot_info.num_rotator, hw_resource->hw_rot_info.has_downscale,
+        hw_resource->hw_rot_info.min_downscale, hw_resource->hw_rot_info.downscale_compression);
+
+  return kErrorNone;
+}
+
+LayerBufferFormat HWInfo::GetSDMFormat(int mdp_format) {
+  switch (mdp_format) {
+  case MDP_ARGB_8888:              return kFormatARGB8888;
+  case MDP_RGBA_8888:              return kFormatRGBA8888;
+  case MDP_BGRA_8888:              return kFormatBGRA8888;
+  case MDP_XRGB_8888:              return kFormatXRGB8888;
+  case MDP_RGBX_8888:              return kFormatRGBX8888;
+  case MDP_BGRX_8888:              return kFormatBGRX8888;
+  case MDP_RGBA_5551:              return kFormatRGBA5551;
+  case MDP_RGBA_4444:              return kFormatRGBA4444;
+  case MDP_RGB_888:                return kFormatRGB888;
+  case MDP_BGR_888:                return kFormatBGR888;
+  case MDP_RGB_565:                return kFormatRGB565;
+  case MDP_BGR_565:                return kFormatBGR565;
+  case MDP_RGBA_8888_UBWC:         return kFormatRGBA8888Ubwc;
+  case MDP_RGBX_8888_UBWC:         return kFormatRGBX8888Ubwc;
+  case MDP_RGB_565_UBWC:           return kFormatBGR565Ubwc;
+  case MDP_Y_CB_CR_H2V2:           return kFormatYCbCr420Planar;
+  case MDP_Y_CR_CB_H2V2:           return kFormatYCrCb420Planar;
+  case MDP_Y_CR_CB_GH2V2:          return kFormatYCrCb420PlanarStride16;
+  case MDP_Y_CBCR_H2V2:            return kFormatYCbCr420SemiPlanar;
+  case MDP_Y_CRCB_H2V2:            return kFormatYCrCb420SemiPlanar;
+  case MDP_Y_CBCR_H2V2_VENUS:      return kFormatYCbCr420SemiPlanarVenus;
+  case MDP_Y_CBCR_H1V2:            return kFormatYCbCr422H1V2SemiPlanar;
+  case MDP_Y_CRCB_H1V2:            return kFormatYCrCb422H1V2SemiPlanar;
+  case MDP_Y_CBCR_H2V1:            return kFormatYCbCr422H2V1SemiPlanar;
+  case MDP_Y_CRCB_H2V1:            return kFormatYCrCb422H2V1SemiPlanar;
+  case MDP_Y_CBCR_H2V2_UBWC:       return kFormatYCbCr420SPVenusUbwc;
+  case MDP_Y_CRCB_H2V2_VENUS:      return kFormatYCrCb420SemiPlanarVenus;
+  case MDP_YCBYCR_H2V1:            return kFormatYCbCr422H2V1Packed;
+  case MDP_RGBA_1010102:           return kFormatRGBA1010102;
+  case MDP_ARGB_2101010:           return kFormatARGB2101010;
+  case MDP_RGBX_1010102:           return kFormatRGBX1010102;
+  case MDP_XRGB_2101010:           return kFormatXRGB2101010;
+  case MDP_BGRA_1010102:           return kFormatBGRA1010102;
+  case MDP_ABGR_2101010:           return kFormatABGR2101010;
+  case MDP_BGRX_1010102:           return kFormatBGRX1010102;
+  case MDP_XBGR_2101010:           return kFormatXBGR2101010;
+  case MDP_RGBA_1010102_UBWC:      return kFormatRGBA1010102Ubwc;
+  case MDP_RGBX_1010102_UBWC:      return kFormatRGBX1010102Ubwc;
+  case MDP_Y_CBCR_H2V2_P010:       return kFormatYCbCr420P010;
+  case MDP_Y_CBCR_H2V2_TP10_UBWC:  return kFormatYCbCr420TP10Ubwc;
+  default:                         return kFormatInvalid;
+  }
+}
+
+void HWInfo::InitSupportedFormatMap(HWResourceInfo *hw_resource) {
+  hw_resource->supported_formats_map.clear();
+
+  for (int sub_blk_type = INT(kHWVIGPipe); sub_blk_type < INT(kHWSubBlockMax); sub_blk_type++) {
+    PopulateSupportedFormatMap(kDefaultFormatSupport[sub_blk_type], MDP_IMGTYPE_LIMIT1,
+                               (HWSubBlockType)sub_blk_type, hw_resource);
+  }
+}
+
+void HWInfo::ParseFormats(char *tokens[], uint32_t token_count, HWSubBlockType sub_blk_type,
+                          HWResourceInfo *hw_resource) {
+  if (token_count > BITS_TO_BYTES(MDP_IMGTYPE_LIMIT1)) {
+    return;
+  }
+
+  std::unique_ptr<std::bitset<8>[]> format_supported(new std::bitset<8>[token_count]);
+  for (uint32_t i = 0; i < token_count; i++) {
+    format_supported[i] = UINT8(atoi(tokens[i]));
+  }
+
+  PopulateSupportedFormatMap(format_supported.get(), (token_count << 3), sub_blk_type, hw_resource);
+}
+
+void HWInfo::PopulateSupportedFormatMap(const std::bitset<8> *format_supported,
+                                        uint32_t format_count, HWSubBlockType sub_blk_type,
+                                        HWResourceInfo *hw_resource) {
+  vector <LayerBufferFormat> supported_sdm_formats;
+  for (uint32_t mdp_format = 0; mdp_format < format_count; mdp_format++) {
+    if (format_supported[mdp_format >> 3][mdp_format & 7]) {
+      LayerBufferFormat sdm_format = GetSDMFormat(INT(mdp_format));
+      if (sdm_format != kFormatInvalid) {
+        supported_sdm_formats.push_back(sdm_format);
+      }
+    }
+  }
+
+  hw_resource->supported_formats_map.erase(sub_blk_type);
+  hw_resource->supported_formats_map.insert(make_pair(sub_blk_type, supported_sdm_formats));
+}
+
+DisplayError HWInfo::GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) {
+  Sys::fstream fs("/sys/devices/virtual/graphics/fb0/msm_fb_type", fstream::in);
+  if (!fs.is_open()) {
+    return kErrorHardware;
+  }
+
+  string line;
+  if (!Sys::getline_(fs, line)) {
+    return kErrorHardware;
+  }
+
+  if (!strncmp(line.c_str(), "dtv panel", strlen("dtv panel")) ||
+      !strncmp(line.c_str(), "dp panel", strlen("dp panel"))) {
+    hw_disp_info->type = kHDMI;
+    DLOGI("First display is HDMI");
+  } else {
+    hw_disp_info->type = kPrimary;
+    DLOGI("First display is internal display");
+  }
+
+  fs.close();
+  fs.open("/sys/devices/virtual/graphics/fb0/connected", fstream::in);
+  if (!fs.is_open()) {
+    // If fb0 is for a DSI/connected panel, then connected node will not exist.
+    hw_disp_info->is_connected = true;
+  } else {
+    if (!Sys::getline_(fs, line)) {
+      return kErrorHardware;
+    }
+
+    hw_disp_info->is_connected =  (!strncmp(line.c_str(), "1", strlen("1")));
+  }
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/core/fb/hw_info.h b/sdm845/sdm/libs/core/fb/hw_info.h
new file mode 100644
index 0000000..cbceba0
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_info.h
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2015 - 2017, 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 <core/sdm_types.h>
+#include <core/core_interface.h>
+#include <private/hw_info_types.h>
+#include <linux/msm_mdp.h>
+#include <bitset>
+
+#include "hw_info_interface.h"
+
+#ifndef MDP_IMGTYPE_END
+#define MDP_IMGTYPE_LIMIT1 0x100
+#endif
+
+namespace sdm {
+
+class HWInfo: public HWInfoInterface {
+ public:
+  virtual ~HWInfo() { delete hw_resource_; }
+  virtual DisplayError GetHWResourceInfo(HWResourceInfo *hw_resource);
+  virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info);
+
+ private:
+  virtual DisplayError GetHWRotatorInfo(HWResourceInfo *hw_resource);
+  virtual DisplayError GetMDSSRotatorInfo(HWResourceInfo *hw_resource);
+  virtual DisplayError GetV4L2RotatorInfo(HWResourceInfo *hw_resource);
+
+  // 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 const std::bitset<8> kDefaultFormatSupport[kHWSubBlockMax][
+                                                        BITS_TO_BYTES(MDP_IMGTYPE_LIMIT1)];
+  static constexpr const char *kRotatorCapsPath = "/sys/devices/virtual/rotator/mdss_rotator/caps";
+  static constexpr const char *kBWModeBitmap
+                                  = "/sys/devices/virtual/graphics/fb0/mdp/bw_mode_bitmap";
+
+  static int ParseString(const char *input, char *tokens[], const uint32_t max_token,
+                         const char *delim, uint32_t *count);
+  DisplayError GetDynamicBWLimits(HWResourceInfo *hw_resource);
+  LayerBufferFormat GetSDMFormat(int mdp_format);
+  void InitSupportedFormatMap(HWResourceInfo *hw_resource);
+  void ParseFormats(char *tokens[], uint32_t token_count, HWSubBlockType sub_block_type,
+                    HWResourceInfo *hw_resource);
+  void PopulateSupportedFormatMap(const std::bitset<8> *format_supported, uint32_t format_count,
+                                  HWSubBlockType sub_blk_type, HWResourceInfo *hw_resource);
+  HWResourceInfo *hw_resource_ = NULL;
+};
+
+}  // namespace sdm
+
+#endif  // __HW_INFO_H__
+
diff --git a/sdm845/sdm/libs/core/fb/hw_primary.cpp b/sdm845/sdm/libs/core/fb/hw_primary.cpp
new file mode 100644
index 0000000..8102e5f
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_primary.cpp
@@ -0,0 +1,679 @@
+/*
+* Copyright (c) 2015 - 2017, 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 <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <utils/debug.h>
+#include <utils/sys.h>
+#include <core/display_interface.h>
+#include <linux/msm_mdp_ext.h>
+#include <utils/rect.h>
+
+#include <string>
+
+#include "hw_primary.h"
+#include "hw_color_manager.h"
+
+#define __CLASS__ "HWPrimary"
+
+#ifndef MDP_COMMIT_CWB_EN
+#define MDP_COMMIT_CWB_EN 0x800
+#endif
+
+#ifndef MDP_COMMIT_CWB_DSPP
+#define MDP_COMMIT_CWB_DSPP 0x1000
+#endif
+
+#ifndef MDP_COMMIT_AVR_EN
+#define MDP_COMMIT_AVR_EN 0x08
+#endif
+
+#ifndef MDP_COMMIT_AVR_ONE_SHOT_MODE
+#define MDP_COMMIT_AVR_ONE_SHOT_MODE 0x10
+#endif
+
+#ifndef MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI
+#define MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI  0x20
+#endif
+
+namespace sdm {
+
+using std::string;
+using std::to_string;
+using std::fstream;
+
+HWPrimary::HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
+  : HWDevice(buffer_sync_handler) {
+  HWDevice::device_type_ = kDevicePrimary;
+  HWDevice::device_name_ = "Primary Display Device";
+  HWDevice::hw_info_intf_ = hw_info_intf;
+}
+
+DisplayError HWPrimary::Init() {
+  DisplayError error = kErrorNone;
+
+  error = HWDevice::Init();
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  mdp_dest_scalar_data_.resize(hw_resource_.hw_dest_scalar_info.count);
+
+  error = PopulateDisplayAttributes();
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  UpdateMixerAttributes();
+
+  // Need to enable HPD, but toggle at start when HDMI is external
+  // This helps for framework reboot or adb shell stop/start
+  EnableHotPlugDetection(0);
+  EnableHotPlugDetection(1);
+  InitializeConfigs();
+
+  avr_prop_disabled_ = Debug::IsAVRDisabled();
+
+  return error;
+}
+
+bool HWPrimary::GetCurrentModeFromSysfs(size_t *curr_x_pixels, size_t *curr_y_pixels) {
+  bool ret = false;
+  string mode_path = fb_path_ + string("0/mode");
+
+  Sys::fstream fs(mode_path, fstream::in);
+  if (!fs.is_open()) {
+    return false;
+  }
+
+  string line;
+  if (Sys::getline_(fs, line)) {
+    // String is of form "U:1600x2560p-0". Documentation/fb/modedb.txt in
+    // kernel has more info on the format.
+    size_t xpos = line.find(':');
+    size_t ypos = line.find('x');
+
+    if (xpos == string::npos || ypos == string::npos) {
+      DLOGI("Resolution switch not supported");
+    } else {
+      *curr_x_pixels = static_cast<size_t>(atoi(line.c_str() + xpos + 1));
+      *curr_y_pixels = static_cast<size_t>(atoi(line.c_str() + ypos + 1));
+      DLOGI("Current Config: %u x %u", *curr_x_pixels, *curr_y_pixels);
+      ret = true;
+    }
+  }
+
+  return ret;
+}
+
+void HWPrimary::InitializeConfigs() {
+  size_t curr_x_pixels = 0;
+  size_t curr_y_pixels = 0;
+
+  if (!GetCurrentModeFromSysfs(&curr_x_pixels, &curr_y_pixels)) {
+    return;
+  }
+
+  string modes_path = string(fb_path_) + string("0/modes");
+
+  Sys::fstream fs(modes_path, fstream::in);
+  if (!fs.is_open()) {
+    DLOGI("Unable to process modes");
+    return;
+  }
+
+  string line;
+  while (Sys::getline_(fs, line)) {
+    DisplayConfigVariableInfo config;
+    // std::getline (unlike ::getline) removes \n while driver expects it in mode, so add back
+    line += '\n';
+    size_t xpos = line.find(':');
+    size_t ypos = line.find('x');
+
+    if (xpos == string::npos || ypos == string::npos) {
+      continue;
+    }
+
+    config.x_pixels = UINT32(atoi(line.c_str() + xpos + 1));
+    config.y_pixels = UINT32(atoi(line.c_str() + ypos + 1));
+    DLOGI("Found mode %d x %d", config.x_pixels, config.y_pixels);
+    display_configs_.push_back(config);
+    display_config_strings_.push_back(string(line.c_str()));
+
+    if (curr_x_pixels == config.x_pixels && curr_y_pixels == config.y_pixels) {
+      active_config_index_ = UINT32(display_configs_.size() - 1);
+      DLOGI("Active config index %u", active_config_index_);
+    }
+  }
+}
+
+DisplayError HWPrimary::GetNumDisplayAttributes(uint32_t *count) {
+  *count = IsResolutionSwitchEnabled() ? UINT32(display_configs_.size()) : 1;
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::GetActiveConfig(uint32_t *active_config_index) {
+  *active_config_index = active_config_index_;
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::GetDisplayAttributes(uint32_t index,
+                                             HWDisplayAttributes *display_attributes) {
+  if (!display_attributes) {
+    return kErrorParameters;
+  }
+
+  if (IsResolutionSwitchEnabled() && index >= display_configs_.size()) {
+    return kErrorParameters;
+  }
+
+  *display_attributes = display_attributes_;
+  if (IsResolutionSwitchEnabled()) {
+    // Overwrite only the parent portion of object
+    display_attributes->x_pixels = display_configs_.at(index).x_pixels;
+    display_attributes->y_pixels = display_configs_.at(index).y_pixels;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::PopulateDisplayAttributes() {
+  DTRACE_SCOPED();
+
+  // Variable screen info
+  fb_var_screeninfo var_screeninfo = {};
+
+  if (Sys::ioctl_(device_fd_, FBIOGET_VSCREENINFO, &var_screeninfo) < 0) {
+    IOCTL_LOGE(FBIOGET_VSCREENINFO, device_type_);
+    return kErrorHardware;
+  }
+
+  // Frame rate
+  msmfb_metadata meta_data = {};
+  meta_data.op = metadata_op_frame_rate;
+  if (Sys::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 320 dpi
+  if (INT(var_screeninfo.width) <= 0 || INT(var_screeninfo.height) <= 0) {
+    var_screeninfo.width  = UINT32(((FLOAT(var_screeninfo.xres) * 25.4f)/320.0f) + 0.5f);
+    var_screeninfo.height = UINT32(((FLOAT(var_screeninfo.yres) * 25.4f)/320.0f) + 0.5f);
+    DLOGW("Driver doesn't report panel physical width and height - defaulting to 320dpi");
+  }
+
+  display_attributes_.x_pixels = var_screeninfo.xres;
+  display_attributes_.y_pixels = var_screeninfo.yres;
+  display_attributes_.v_front_porch = var_screeninfo.lower_margin;
+  display_attributes_.v_back_porch = var_screeninfo.upper_margin;
+  display_attributes_.v_pulse_width = 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 + h_blanking;
+  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.right_split ||
+      (var_screeninfo.xres > hw_resource_.max_mixer_width));
+  display_attributes_.h_total += (display_attributes_.is_device_split ||
+    hw_panel_info_.ping_pong_split)? h_blanking : 0;
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::SetDisplayAttributes(uint32_t index) {
+  DisplayError ret = kErrorNone;
+
+  if (!IsResolutionSwitchEnabled()) {
+    return kErrorNotSupported;
+  }
+
+  if (index >= display_configs_.size()) {
+    return kErrorParameters;
+  }
+
+  string mode_path = string(fb_path_) + string("0/mode");
+  int fd = Sys::open_(mode_path.c_str(), O_WRONLY);
+
+  if (fd < 0) {
+    DLOGE("Opening mode failed");
+    return kErrorNotSupported;
+  }
+
+  ssize_t written = Sys::pwrite_(fd, display_config_strings_.at(index).c_str(),
+                                 display_config_strings_.at(index).length(), 0);
+  if (written > 0) {
+    DLOGI("Successfully set config %u", index);
+    PopulateHWPanelInfo();
+    PopulateDisplayAttributes();
+    UpdateMixerAttributes();
+    active_config_index_ = index;
+  } else {
+    DLOGE("Writing config index %u failed with error: %s", index, strerror(errno));
+    ret = kErrorParameters;
+  }
+
+  Sys::close_(fd);
+
+  return ret;
+}
+
+DisplayError HWPrimary::SetRefreshRate(uint32_t refresh_rate) {
+  char node_path[kMaxStringLength] = {0};
+
+  if (hw_resource_.has_avr && !avr_prop_disabled_) {
+    return kErrorNotSupported;
+  }
+
+  snprintf(node_path, sizeof(node_path), "%s%d/dynamic_fps", fb_path_, fb_node_index_);
+
+  int fd = Sys::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);
+  DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", refresh_rate);
+  ssize_t len = Sys::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));
+    Sys::close_(fd);
+    return kErrorUndefined;
+  }
+  Sys::close_(fd);
+
+  DisplayError error = PopulateDisplayAttributes();
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::GetConfigIndex(uint32_t mode, uint32_t *index) {
+  return HWDevice::GetConfigIndex(mode, index);
+}
+
+DisplayError HWPrimary::PowerOff() {
+  if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
+    IOCTL_LOGE(FB_BLANK_POWERDOWN, device_type_);
+    return kErrorHardware;
+  }
+
+  auto_refresh_ = false;
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::Doze() {
+  if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_NORMAL) < 0) {
+    IOCTL_LOGE(FB_BLANK_NORMAL, device_type_);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::DozeSuspend() {
+  if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_VSYNC_SUSPEND) < 0) {
+    IOCTL_LOGE(FB_BLANK_VSYNC_SUSPEND, device_type_);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::Validate(HWLayers *hw_layers) {
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  LayerStack *stack = hw_layer_info.stack;
+
+  HWDevice::ResetDisplayParams();
+
+  mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+
+  LayerRect left_roi = hw_layer_info.left_frame_roi.at(0);
+  LayerRect right_roi = hw_layer_info.right_frame_roi.at(0);
+
+  mdp_commit.left_roi.x = UINT32(left_roi.left);
+  mdp_commit.left_roi.y = UINT32(left_roi.top);
+  mdp_commit.left_roi.w = UINT32(left_roi.right - left_roi.left);
+  mdp_commit.left_roi.h = UINT32(left_roi.bottom - left_roi.top);
+
+  // Update second roi information in right_roi
+  if (hw_layer_info.left_frame_roi.size() == 2) {
+    mdp_commit.flags |= MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI;
+    right_roi = hw_layer_info.left_frame_roi.at(1);
+  }
+
+  // SDM treats ROI as one full coordinate system.
+  // In case source split is disabled, However, Driver assumes Mixer to operate in
+  // different co-ordinate system.
+  if (IsValid(right_roi)) {
+    mdp_commit.right_roi.x = UINT32(right_roi.left);
+    if (!hw_resource_.is_src_split) {
+      mdp_commit.right_roi.x = UINT32(right_roi.left) - mixer_attributes_.split_left;
+    }
+    mdp_commit.right_roi.y = UINT32(right_roi.top);
+    mdp_commit.right_roi.w = UINT32(right_roi.right - right_roi.left);
+    mdp_commit.right_roi.h = UINT32(right_roi.bottom - right_roi.top);
+  }
+
+  if (stack->output_buffer && hw_resource_.has_concurrent_writeback) {
+    LayerBuffer *output_buffer = stack->output_buffer;
+    mdp_out_layer_.writeback_ndx = hw_resource_.writeback_index;
+    mdp_out_layer_.buffer.width = output_buffer->unaligned_width;
+    mdp_out_layer_.buffer.height = output_buffer->unaligned_height;
+    mdp_out_layer_.buffer.comp_ratio.denom = 1000;
+    mdp_out_layer_.buffer.comp_ratio.numer = UINT32(hw_layers->output_compression * 1000);
+    mdp_out_layer_.buffer.fence = -1;
+#ifdef OUT_LAYER_COLOR_SPACE
+    SetCSC(output_buffer->color_metadata, &mdp_out_layer_.color_space);
+#endif
+    SetFormat(output_buffer->format, &mdp_out_layer_.buffer.format);
+    mdp_commit.flags |= MDP_COMMIT_CWB_EN;
+    mdp_commit.flags |= (stack->flags.post_processed_output) ? MDP_COMMIT_CWB_DSPP : 0;
+    DLOGI_IF(kTagDriverConfig, "****************** Conc WB Output buffer Info ******************");
+    DLOGI_IF(kTagDriverConfig, "out_w %d, out_h %d, out_f %d, wb_id %d DSPP output %d",
+             mdp_out_layer_.buffer.width, mdp_out_layer_.buffer.height,
+             mdp_out_layer_.buffer.format, mdp_out_layer_.writeback_ndx,
+             stack->flags.post_processed_output);
+    DLOGI_IF(kTagDriverConfig, "****************************************************************");
+  }
+
+  if (hw_resource_.has_avr) {
+    SetAVRFlags(hw_layers->hw_avr_info, &mdp_commit.flags);
+  }
+
+  return HWDevice::Validate(hw_layers);
+}
+
+DisplayError HWPrimary::Commit(HWLayers *hw_layers) {
+  LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+
+  if (hw_resource_.has_concurrent_writeback && 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;
+      mdp_out_layer_.buffer.fence = -1;
+
+      DLOGI_IF(kTagDriverConfig, "****************** Conc WB Output buffer Info ****************");
+      DLOGI_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d",
+               mdp_out_layer_.buffer.planes[0].fd, mdp_out_layer_.buffer.planes[0].offset,
+               mdp_out_layer_.buffer.planes[0].stride);
+      DLOGI_IF(kTagDriverConfig, "**************************************************************");
+    } else {
+      DLOGE("Invalid output buffer fd");
+      return kErrorParameters;
+    }
+  }
+
+  DisplayError ret = HWDevice::Commit(hw_layers);
+
+  if (ret == kErrorNone && hw_resource_.has_concurrent_writeback && output_buffer) {
+    output_buffer->release_fence_fd = mdp_out_layer_.buffer.fence;
+  }
+
+  return ret;
+}
+
+void HWPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+  char node_path[kMaxStringLength] = {0};
+
+  DLOGI_IF(kTagDriverConfig, "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 = Sys::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 = Sys::pwrite_(fd, timeout_string, strlen(timeout_string), 0);
+  if (length <= 0) {
+    DLOGE("Unable to write into %s, node %s", node_path, strerror(errno));
+  }
+
+  Sys::close_(fd);
+}
+
+DisplayError HWPrimary::SetVSyncState(bool enable) {
+  DTRACE_SCOPED();
+  return HWDevice::SetVSyncState(enable);
+}
+
+DisplayError HWPrimary::SetDisplayMode(const HWDisplayMode hw_display_mode) {
+  uint32_t mode = kModeDefault;
+
+  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 (Sys::ioctl_(device_fd_, INT(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;
+}
+
+DisplayError HWPrimary::SetPanelBrightness(int level) {
+  char buffer[kMaxSysfsCommandLength] = {0};
+
+  DLOGV_IF(kTagDriverConfig, "Set brightness level to %d", level);
+  int fd = Sys::open_(kBrightnessNode, O_RDWR);
+  if (fd < 0) {
+    DLOGV_IF(kTagDriverConfig, "Failed to open node = %s, error = %s ", kBrightnessNode,
+             strerror(errno));
+    return kErrorFileDescriptor;
+  }
+
+  int32_t bytes = snprintf(buffer, kMaxSysfsCommandLength, "%d\n", level);
+  if (bytes < 0) {
+    DLOGV_IF(kTagDriverConfig, "Failed to copy new brightness level = %d", level);
+    Sys::close_(fd);
+    return kErrorUndefined;
+  }
+
+  ssize_t ret = Sys::pwrite_(fd, buffer, static_cast<size_t>(bytes), 0);
+  if (ret <= 0) {
+    DLOGV_IF(kTagDriverConfig, "Failed to write to node = %s, error = %s ", kBrightnessNode,
+             strerror(errno));
+    Sys::close_(fd);
+    return kErrorUndefined;
+  }
+  Sys::close_(fd);
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::GetPanelBrightness(int *level) {
+  char brightness[kMaxStringLength] = {0};
+
+  if (!level) {
+    DLOGV_IF(kTagDriverConfig, "Invalid input, null pointer.");
+    return kErrorParameters;
+  }
+
+  int fd = Sys::open_(kBrightnessNode, O_RDWR);
+  if (fd < 0) {
+    DLOGV_IF(kTagDriverConfig, "Failed to open brightness node = %s, error = %s", kBrightnessNode,
+             strerror(errno));
+    return kErrorFileDescriptor;
+  }
+
+  if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
+    *level = atoi(brightness);
+    DLOGV_IF(kTagDriverConfig, "Brightness level = %d", *level);
+  }
+  Sys::close_(fd);
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::CachePanelBrightness(int level) {
+  bl_level_update_commit = level;
+  bl_update_commit = true;
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::SetAutoRefresh(bool enable) {
+  const int kWriteLength = 2;
+  char buffer[kWriteLength] = {'\0'};
+  ssize_t bytes = snprintf(buffer, kWriteLength, "%d", enable);
+
+  if (enable == auto_refresh_) {
+    return kErrorNone;
+  }
+
+  if (HWDevice::SysFsWrite(kAutoRefreshNode, buffer, bytes) <= 0) {  // Returns bytes written
+    return kErrorUndefined;
+  }
+
+  auto_refresh_ = enable;
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::GetPPFeaturesVersion(PPFeatureVersion *vers) {
+  mdp_pp_feature_version version = {};
+
+#ifdef PA_DITHER
+  uint32_t feature_id_mapping[kMaxNumPPFeatures] = { PCC, IGC, GC, GC, PA,
+                                                     DITHER, GAMUT, PA_DITHER };
+#else
+  uint32_t feature_id_mapping[kMaxNumPPFeatures] = { PCC, IGC, GC, GC, PA, DITHER, GAMUT };
+#endif
+
+  for (int i(0); i < kMaxNumPPFeatures; i++) {
+    version.pp_feature = feature_id_mapping[i];
+
+    if (Sys::ioctl_(device_fd_,  INT(MSMFB_MDP_PP_GET_FEATURE_VERSION), &version) < 0) {
+      IOCTL_LOGE(MSMFB_MDP_PP_GET_FEATURE_VERSION, device_type_);
+      return kErrorHardware;
+    }
+    vers->version[i] = version.version_info;
+  }
+
+  return kErrorNone;
+}
+
+// It was entered with PPFeaturesConfig::locker_ being hold.
+DisplayError HWPrimary::SetPPFeatures(PPFeaturesConfig *feature_list) {
+  msmfb_mdp_pp kernel_params = {};
+  int ret = 0;
+  PPFeatureInfo *feature = NULL;
+
+  while (true) {
+    ret = feature_list->RetrieveNextFeature(&feature);
+    if (ret)
+        break;
+
+    if (feature) {
+      DLOGV_IF(kTagDriverConfig, "feature_id = %d", feature->feature_id_);
+
+      if ((feature->feature_id_ < kMaxNumPPFeatures)) {
+        HWColorManager::SetFeature[feature->feature_id_](*feature, &kernel_params);
+        if (Sys::ioctl_(device_fd_, INT(MSMFB_MDP_PP), &kernel_params) < 0) {
+          IOCTL_LOGE(MSMFB_MDP_PP, device_type_);
+
+          feature_list->Reset();
+          return kErrorHardware;
+        }
+      }
+    }
+  }  // while(true)
+
+  // Once all features were consumed, then destroy all feature instance from feature_list,
+  // Then mark it as non-dirty of PPFeaturesConfig cache.
+  feature_list->Reset();
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+  if (IsResolutionSwitchEnabled()) {
+    return kErrorNotSupported;
+  }
+
+  return HWDevice::SetMixerAttributes(mixer_attributes);
+}
+
+void HWPrimary::UpdateMixerAttributes() {
+  mixer_attributes_.width = display_attributes_.x_pixels;
+  mixer_attributes_.height = display_attributes_.y_pixels;
+  mixer_attributes_.split_left = display_attributes_.is_device_split ?
+      hw_panel_info_.split_info.left_split : mixer_attributes_.width;
+}
+
+void HWPrimary::SetAVRFlags(const HWAVRInfo &hw_avr_info, uint32_t *avr_flags) {
+  if (hw_avr_info.enable) {
+    *avr_flags |= MDP_COMMIT_AVR_EN;
+  }
+
+  if (hw_avr_info.mode == kOneShotMode) {
+    *avr_flags |= MDP_COMMIT_AVR_ONE_SHOT_MODE;
+  }
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/core/fb/hw_primary.h b/sdm845/sdm/libs/core/fb/hw_primary.h
new file mode 100644
index 0000000..38b3b9a
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_primary.h
@@ -0,0 +1,95 @@
+/*
+* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_PRIMARY_H__
+#define __HW_PRIMARY_H__
+
+#include <sys/poll.h>
+#include <vector>
+#include <string>
+
+#include "hw_device.h"
+
+namespace sdm {
+
+class HWPrimary : public HWDevice {
+ public:
+  HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
+
+ protected:
+  virtual DisplayError Init();
+  virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+  virtual DisplayError GetActiveConfig(uint32_t *active_config);
+  virtual DisplayError GetDisplayAttributes(uint32_t index,
+                                            HWDisplayAttributes *display_attributes);
+  virtual DisplayError SetDisplayAttributes(uint32_t index);
+  virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+  virtual DisplayError PowerOff();
+  virtual DisplayError Doze();
+  virtual DisplayError DozeSuspend();
+  virtual DisplayError Validate(HWLayers *hw_layers);
+  virtual DisplayError Commit(HWLayers *hw_layers);
+  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);
+  virtual DisplayError SetPanelBrightness(int level);
+  virtual DisplayError CachePanelBrightness(int level);
+  virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
+  virtual DisplayError SetPPFeatures(PPFeaturesConfig *feature_list);
+  virtual DisplayError GetPanelBrightness(int *level);
+  virtual DisplayError SetAutoRefresh(bool enable);
+  virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
+
+ private:
+  // Panel modes for the MSMFB_LPM_ENABLE ioctl
+  enum {
+    kModeLPMVideo,
+    kModeLPMCommand,
+  };
+
+  enum {
+    kMaxSysfsCommandLength = 12,
+  };
+
+  DisplayError PopulateDisplayAttributes();
+  void InitializeConfigs();
+  bool IsResolutionSwitchEnabled() { return !display_configs_.empty(); }
+  bool GetCurrentModeFromSysfs(size_t *curr_x_pixels, size_t *curr_y_pixels);
+  void UpdateMixerAttributes();
+  void SetAVRFlags(const HWAVRInfo &hw_avr_info, uint32_t *avr_flags);
+
+  std::vector<DisplayConfigVariableInfo> display_configs_;
+  std::vector<std::string> display_config_strings_;
+  uint32_t active_config_index_ = 0;
+  const char *kBrightnessNode = "/sys/class/leds/lcd-backlight/brightness";
+  const char *kAutoRefreshNode = "/sys/devices/virtual/graphics/fb0/msm_cmd_autorefresh_en";
+  bool auto_refresh_ = false;
+  bool avr_prop_disabled_ = false;
+};
+
+}  // namespace sdm
+
+#endif  // __HW_PRIMARY_H__
+
diff --git a/sdm845/sdm/libs/core/fb/hw_scale.cpp b/sdm845/sdm/libs/core/fb/hw_scale.cpp
new file mode 100644
index 0000000..e44af5d
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_scale.cpp
@@ -0,0 +1,314 @@
+/*
+* Copyright (c) 2016-2017, 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/debug.h>
+#include "hw_scale.h"
+
+#define __CLASS__ "HWScale"
+
+namespace sdm {
+
+DisplayError HWScale::Create(HWScale **intf, bool has_qseed3) {
+  if (has_qseed3) {
+    *intf = new HWScaleV2();
+  } else {
+    *intf = new HWScaleV1();
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWScale::Destroy(HWScale *intf) {
+  delete intf;
+
+  return kErrorNone;
+}
+
+void HWScaleV1::SetHWScaleData(const HWScaleData &scale_data, uint32_t index,
+                               mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type) {
+  if (!scale_data.enable.scale) {
+    return;
+  }
+
+  if (sub_block_type == kHWDestinationScalar) {
+    return;
+  }
+
+  mdp_input_layer *mdp_layer = &mdp_commit->input_layers[index];
+  mdp_layer->flags |= MDP_LAYER_ENABLE_PIXEL_EXT;
+  mdp_scale_data *mdp_scale = &scale_data_v1_.at(index);
+  mdp_scale->enable_pxl_ext = scale_data.enable.scale;
+  for (int i = 0; i < MAX_PLANES; i++) {
+    const HWPlane &plane = scale_data.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;
+  }
+
+  return;
+}
+
+void* HWScaleV1::GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type) {
+  if (sub_block_type != kHWDestinationScalar) {
+    return &scale_data_v1_.at(index);
+  }
+
+  return NULL;
+}
+
+void HWScaleV1::DumpScaleData(void *mdp_scale) {
+  if (!mdp_scale) {
+    return;
+  }
+
+  mdp_scale_data *scale = reinterpret_cast<mdp_scale_data *>(mdp_scale);
+  if (scale->enable_pxl_ext) {
+    DLOGV_IF(kTagDriverConfig, "Scale Enable = %d", scale->enable_pxl_ext);
+    for (int j = 0; j < MAX_PLANES; j++) {
+      DLOGV_IF(kTagDriverConfig, "Scale Data[%d] : Phase=[%x %x %x %x] Pixel_Ext=[%d %d %d %d]",
+               j, scale->init_phase_x[j], scale->phase_step_x[j], scale->init_phase_y[j],
+               scale->phase_step_y[j], scale->num_ext_pxls_left[j], scale->num_ext_pxls_top[j],
+               scale->num_ext_pxls_right[j], scale->num_ext_pxls_btm[j]);
+      DLOGV_IF(kTagDriverConfig, "Fetch=[%d %d %d %d]  Repeat=[%d %d %d %d]  roi_width = %d",
+               scale->left_ftch[j], scale->top_ftch[j], scale->right_ftch[j], scale->btm_ftch[j],
+               scale->left_rpt[j], scale->top_rpt[j], scale->right_rpt[j], scale->btm_rpt[j],
+               scale->roi_w[j]);
+    }
+  }
+
+  return;
+}
+
+void HWScaleV2::SetHWScaleData(const HWScaleData &scale_data, uint32_t index,
+                               mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type) {
+  if (!scale_data.enable.scale && !scale_data.enable.direction_detection &&
+      !scale_data.enable.detail_enhance ) {
+    return;
+  }
+
+  mdp_scale_data_v2 *mdp_scale;
+  if (sub_block_type != kHWDestinationScalar) {
+    mdp_input_layer *mdp_layer = &mdp_commit->input_layers[index];
+    mdp_layer->flags |= MDP_LAYER_ENABLE_QSEED3_SCALE;
+    mdp_scale = &scale_data_v2_.at(index);
+  } else {
+    mdp_scale_data_v2 mdp_dest_scale = {0};
+
+    dest_scale_data_v2_.insert(std::make_pair(index, mdp_dest_scale));
+    mdp_scale = &dest_scale_data_v2_[index];
+  }
+
+  mdp_scale->enable = (scale_data.enable.scale ? ENABLE_SCALE : 0) |
+                      (scale_data.enable.direction_detection ? ENABLE_DIRECTION_DETECTION : 0) |
+                      (scale_data.enable.detail_enhance ? ENABLE_DETAIL_ENHANCE : 0);
+
+  if (sub_block_type == kHWDestinationScalar) {
+    mdp_destination_scaler_data *mdp_dest_scalar =
+      reinterpret_cast<mdp_destination_scaler_data *>(mdp_commit->dest_scaler);
+
+    mdp_dest_scalar[index].flags = mdp_scale->enable ? MDP_DESTSCALER_ENABLE : 0;
+
+    if (scale_data.enable.detail_enhance) {
+      mdp_dest_scalar[index].flags |= MDP_DESTSCALER_ENHANCER_UPDATE;
+    }
+  }
+
+  for (int i = 0; i < MAX_PLANES; i++) {
+    const HWPlane &plane = scale_data.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] = UINT32(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] = UINT32(plane.top.extension);
+    mdp_scale->top_ftch[i] = UINT32(plane.top.overfetch);
+    mdp_scale->top_rpt[i] = UINT32(plane.top.repeat);
+
+    mdp_scale->num_ext_pxls_right[i] = UINT32(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] = UINT32(plane.bottom.extension);
+    mdp_scale->btm_ftch[i] = UINT32(plane.bottom.overfetch);
+    mdp_scale->btm_rpt[i] = UINT32(plane.bottom.repeat);
+
+    mdp_scale->roi_w[i] = plane.roi_width;
+
+    mdp_scale->preload_x[i] = UINT32(plane.preload_x);
+    mdp_scale->preload_y[i] = UINT32(plane.preload_y);
+
+    mdp_scale->src_width[i] = plane.src_width;
+    mdp_scale->src_height[i] = plane.src_height;
+  }
+
+  mdp_scale->dst_width = scale_data.dst_width;
+  mdp_scale->dst_height = scale_data.dst_height;
+
+  mdp_scale->y_rgb_filter_cfg = GetMDPScalingFilter(scale_data.y_rgb_filter_cfg);
+  mdp_scale->uv_filter_cfg = GetMDPScalingFilter(scale_data.uv_filter_cfg);
+  mdp_scale->alpha_filter_cfg = GetMDPAlphaInterpolation(scale_data.alpha_filter_cfg);
+  mdp_scale->blend_cfg = scale_data.blend_cfg;
+
+  mdp_scale->lut_flag = (scale_data.lut_flag.lut_swap ? SCALER_LUT_SWAP : 0) |
+                        (scale_data.lut_flag.lut_dir_wr ? SCALER_LUT_DIR_WR : 0) |
+                        (scale_data.lut_flag.lut_y_cir_wr ? SCALER_LUT_Y_CIR_WR : 0) |
+                        (scale_data.lut_flag.lut_uv_cir_wr ? SCALER_LUT_UV_CIR_WR : 0) |
+                        (scale_data.lut_flag.lut_y_sep_wr ? SCALER_LUT_Y_SEP_WR : 0) |
+                        (scale_data.lut_flag.lut_uv_sep_wr ? SCALER_LUT_UV_SEP_WR : 0);
+
+  mdp_scale->dir_lut_idx = scale_data.dir_lut_idx;
+  mdp_scale->y_rgb_cir_lut_idx = scale_data.y_rgb_cir_lut_idx;
+  mdp_scale->uv_cir_lut_idx = scale_data.uv_cir_lut_idx;
+  mdp_scale->y_rgb_sep_lut_idx = scale_data.y_rgb_sep_lut_idx;
+  mdp_scale->uv_sep_lut_idx = scale_data.uv_sep_lut_idx;
+
+  if (mdp_scale->enable & ENABLE_DETAIL_ENHANCE) {
+    mdp_det_enhance_data *mdp_det_enhance = &mdp_scale->detail_enhance;
+    mdp_det_enhance->enable = scale_data.detail_enhance.enable;
+    mdp_det_enhance->sharpen_level1 = scale_data.detail_enhance.sharpen_level1;
+    mdp_det_enhance->sharpen_level2 = scale_data.detail_enhance.sharpen_level2;
+    mdp_det_enhance->clip = scale_data.detail_enhance.clip;
+    mdp_det_enhance->limit = scale_data.detail_enhance.limit;
+    mdp_det_enhance->thr_quiet = scale_data.detail_enhance.thr_quiet;
+    mdp_det_enhance->thr_dieout = scale_data.detail_enhance.thr_dieout;
+    mdp_det_enhance->thr_low = scale_data.detail_enhance.thr_low;
+    mdp_det_enhance->thr_high = scale_data.detail_enhance.thr_high;
+    mdp_det_enhance->prec_shift = scale_data.detail_enhance.prec_shift;
+
+    for (int i = 0; i < MAX_DET_CURVES; i++) {
+      mdp_det_enhance->adjust_a[i] = scale_data.detail_enhance.adjust_a[i];
+      mdp_det_enhance->adjust_b[i] = scale_data.detail_enhance.adjust_b[i];
+      mdp_det_enhance->adjust_c[i] = scale_data.detail_enhance.adjust_c[i];
+    }
+  }
+
+  return;
+}
+
+void* HWScaleV2::GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type) {
+  if (sub_block_type != kHWDestinationScalar) {
+    return &scale_data_v2_.at(index);
+  } else {
+    return &dest_scale_data_v2_[index];
+  }
+}
+
+uint32_t HWScaleV2::GetMDPScalingFilter(ScalingFilterConfig filter_cfg) {
+  switch (filter_cfg) {
+  case kFilterEdgeDirected:
+    return FILTER_EDGE_DIRECTED_2D;
+  case kFilterCircular:
+    return FILTER_CIRCULAR_2D;
+  case kFilterSeparable:
+    return FILTER_SEPARABLE_1D;
+  case kFilterBilinear:
+    return FILTER_BILINEAR;
+  default:
+    DLOGE("Invalid Scaling Filter");
+    return kFilterMax;
+  }
+}
+
+uint32_t HWScaleV2::GetMDPAlphaInterpolation(HWAlphaInterpolation alpha_filter_cfg) {
+  switch (alpha_filter_cfg) {
+  case kInterpolationPixelRepeat:
+    return FILTER_ALPHA_DROP_REPEAT;
+  case kInterpolationBilinear:
+    return FILTER_ALPHA_BILINEAR;
+  default:
+    DLOGE("Invalid Alpha Interpolation");
+    return kInterpolationMax;
+  }
+}
+
+void HWScaleV2::DumpScaleData(void *mdp_scale) {
+  if (!mdp_scale) {
+    return;
+  }
+
+  mdp_scale_data_v2 *scale = reinterpret_cast<mdp_scale_data_v2 *>(mdp_scale);
+  if (scale->enable) {
+    DLOGV_IF(kTagDriverConfig, "Scale Enable = %d", scale->enable);
+    for (int j = 0; j < MAX_PLANES; j++) {
+      DLOGV_IF(kTagDriverConfig, "Scale Data[%d]: Phase_init[x y]=[%x %x] Phase_step:[x y]=[%x %x]",
+        j, scale->init_phase_x[j], scale->init_phase_y[j], scale->phase_step_x[j],
+        scale->phase_step_y[j]);
+      DLOGV_IF(kTagDriverConfig, "Preload[x y]=[%x %x], Pixel Ext=[%d %d] Ovfetch=[%d %d %d %d]",
+        scale->preload_x[j], scale->preload_y[j], scale->num_ext_pxls_left[j],
+        scale->num_ext_pxls_top[j], scale->left_ftch[j], scale->top_ftch[j], scale->right_ftch[j],
+        scale->btm_ftch[j]);
+      DLOGV_IF(kTagDriverConfig, "Repeat=[%d %d %d %d] Src[w x h]=[%d %d] roi_width = %d",
+        scale->left_rpt[j], scale->top_rpt[j], scale->right_rpt[j], scale->btm_rpt[j],
+        scale->src_width[j], scale->src_height[j], scale->roi_w[j]);
+    }
+
+    DLOGV_IF(kTagDriverConfig, "LUT flags = %d", scale->lut_flag);
+    DLOGV_IF(kTagDriverConfig, "y_rgb_filter=%d, uv_filter=%d, alpha_filter=%d, blend_cfg=%d",
+      scale->y_rgb_filter_cfg, scale->uv_filter_cfg, scale->alpha_filter_cfg, scale->blend_cfg);
+    DLOGV_IF(kTagDriverConfig, "dir_lut=%d, y_rgb_cir=%d, uv_cir=%d, y_rgb_sep=%d, uv_sep=%d",
+      scale->dir_lut_idx, scale->y_rgb_cir_lut_idx, scale->uv_cir_lut_idx,
+      scale->y_rgb_sep_lut_idx, scale->uv_sep_lut_idx);
+    if (scale->enable & ENABLE_DETAIL_ENHANCE) {
+      mdp_det_enhance_data *de = &scale->detail_enhance;
+      DLOGV_IF(kTagDriverConfig, "Detail Enhance: enable: %d sharpen_level1: %d sharpen_level2: %d",
+        de->enable, de->sharpen_level1, de->sharpen_level2);
+      DLOGV_IF(kTagDriverConfig, "clip: %d limit:%d thr_quiet: %d thr_dieout: %d",
+        de->clip, de->limit, de->thr_quiet, de->thr_dieout);
+      DLOGV_IF(kTagDriverConfig, "thr_low: %d thr_high: %d prec_shift: %d", de->thr_low,
+        de->thr_high, de->prec_shift);
+      for (uint32_t i = 0; i < MAX_DET_CURVES; i++) {
+        DLOGV_IF(kTagDriverConfig, "adjust_a[%d]: %d adjust_b[%d]: %d adjust_c[%d]: %d", i,
+          de->adjust_a[i], i, de->adjust_b[i], i, de->adjust_c[i]);
+      }
+    }
+  }
+
+  return;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/fb/hw_scale.h b/sdm845/sdm/libs/core/fb/hw_scale.h
new file mode 100644
index 0000000..7590833
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_scale.h
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_SCALE_H__
+#define __HW_SCALE_H__
+
+#include <linux/msm_mdp_ext.h>
+#include <private/hw_info_types.h>
+
+#include <cstring>
+#include <array>
+#include <map>
+
+namespace sdm {
+
+class HWScale {
+ public:
+  static DisplayError Create(HWScale **intf, bool has_qseed3);
+  static DisplayError Destroy(HWScale *intf);
+
+  virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
+                              mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type) = 0;
+  virtual void* GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type) = 0;
+  virtual void DumpScaleData(void *mdp_scale) = 0;
+  virtual void ResetScaleParams() = 0;
+ protected:
+  virtual ~HWScale() { }
+};
+
+class HWScaleV1 : public HWScale {
+ public:
+  virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
+                              mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type);
+  virtual void* GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type);
+  virtual void DumpScaleData(void *mdp_scale);
+  virtual void ResetScaleParams() { scale_data_v1_ = {}; }
+
+ protected:
+  ~HWScaleV1() {}
+  std::array<mdp_scale_data, (kMaxSDELayers * 2)> scale_data_v1_ = {};
+};
+
+class HWScaleV2 : public HWScale {
+ public:
+  virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
+                              mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type);
+  virtual void* GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type);
+  virtual void DumpScaleData(void *mdp_scale);
+  virtual void ResetScaleParams() { scale_data_v2_ = {}; dest_scale_data_v2_ = {}; }
+
+ protected:
+  ~HWScaleV2() {}
+  std::array<mdp_scale_data_v2, (kMaxSDELayers * 2)> scale_data_v2_ = {};
+  std::map<uint32_t, mdp_scale_data_v2> dest_scale_data_v2_ = {};
+
+ private:
+  uint32_t GetMDPAlphaInterpolation(HWAlphaInterpolation alpha_filter_cfg);
+  uint32_t GetMDPScalingFilter(ScalingFilterConfig filter_cfg);
+};
+
+}  // namespace sdm
+
+#endif  // __HW_SCALE_H__
+
diff --git a/sdm845/sdm/libs/core/fb/hw_virtual.cpp b/sdm845/sdm/libs/core/fb/hw_virtual.cpp
new file mode 100644
index 0000000..21017a5
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_virtual.cpp
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/debug.h>
+#include "hw_virtual.h"
+
+#define __CLASS__ "HWVirtual"
+
+namespace sdm {
+
+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::Validate(HWLayers *hw_layers) {
+  HWDevice::ResetDisplayParams();
+  return HWDevice::Validate(hw_layers);
+}
+
+DisplayError HWVirtual::GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
+  mixer_attributes->width = display_attributes_.x_pixels;
+  mixer_attributes->height = display_attributes_.y_pixels;
+  mixer_attributes_.split_left = display_attributes_.is_device_split ?
+      (display_attributes_.x_pixels / 2) : mixer_attributes_.width;
+
+  return kErrorNone;
+}
+
+DisplayError HWVirtual::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) {
+  if (display_attributes.x_pixels == 0 || display_attributes.y_pixels == 0) {
+    return kErrorParameters;
+  }
+
+  display_attributes_ = display_attributes;
+
+  if (display_attributes_.x_pixels > hw_resource_.max_mixer_width) {
+    display_attributes_.is_device_split = true;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWVirtual::GetDisplayAttributes(uint32_t index,
+                                             HWDisplayAttributes *display_attributes) {
+  display_attributes->fps = 60;
+  // TODO(user): Need to update WB fps
+
+  return kErrorNone;
+}
+
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/core/fb/hw_virtual.h b/sdm845/sdm/libs/core/fb/hw_virtual.h
new file mode 100644
index 0000000..1c204cd
--- /dev/null
+++ b/sdm845/sdm/libs/core/fb/hw_virtual.h
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_VIRTUAL_H__
+#define __HW_VIRTUAL_H__
+
+#include "hw_device.h"
+
+namespace sdm {
+
+class HWVirtual : public HWDevice {
+ public:
+  HWVirtual(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
+  virtual DisplayError SetVSyncState(bool enable) { return kErrorNotSupported; }
+  virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
+  virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
+  virtual DisplayError GetDisplayAttributes(uint32_t index,
+                                            HWDisplayAttributes *display_attributes);
+
+ protected:
+  virtual DisplayError Init();
+  virtual DisplayError Validate(HWLayers *hw_layers);
+};
+
+}  // namespace sdm
+
+#endif  // __HW_VIRTUAL_H__
+
diff --git a/sdm845/sdm/libs/core/hw_events_interface.cpp b/sdm845/sdm/libs/core/hw_events_interface.cpp
new file mode 100644
index 0000000..ed62b86
--- /dev/null
+++ b/sdm845/sdm/libs/core/hw_events_interface.cpp
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2017, 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/utils.h>
+#include <vector>
+
+#include "hw_events_interface.h"
+#include "fb/hw_events.h"
+#ifdef COMPILE_DRM
+#include "drm/hw_events_drm.h"
+#endif
+
+#define __CLASS__ "HWEventsInterface"
+
+namespace sdm {
+
+DisplayError HWEventsInterface::Create(int display_type, HWEventHandler *event_handler,
+                                       const std::vector<HWEvent> &event_list,
+                                       HWEventsInterface **intf) {
+  DisplayError error = kErrorNone;
+  HWEventsInterface *hw_events = nullptr;
+  if (GetDriverType() == DriverType::FB) {
+    hw_events = new HWEvents();
+  } else {
+#ifdef COMPILE_DRM
+    hw_events = new HWEventsDRM();
+#endif
+  }
+
+  error = hw_events->Init(display_type, event_handler, event_list);
+  if (error != kErrorNone) {
+    delete hw_events;
+  } else {
+    *intf = hw_events;
+  }
+
+  return error;
+}
+
+DisplayError HWEventsInterface::Destroy(HWEventsInterface *intf) {
+  if (intf) {
+    intf->Deinit();
+    delete intf;
+  }
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/hw_events_interface.h b/sdm845/sdm/libs/core/hw_events_interface.h
new file mode 100644
index 0000000..482e077
--- /dev/null
+++ b/sdm845/sdm/libs/core/hw_events_interface.h
@@ -0,0 +1,65 @@
+/*
+* Copyright (c) 2016-2017, 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_EVENTS_INTERFACE_H__
+#define __HW_EVENTS_INTERFACE_H__
+
+#include <private/hw_info_types.h>
+#include <inttypes.h>
+#include <utility>
+#include <vector>
+
+namespace sdm {
+
+class HWEventHandler;
+
+enum HWEvent {
+  VSYNC = 0,
+  EXIT,
+  IDLE_NOTIFY,
+  CEC_READ_MESSAGE,
+  SHOW_BLANK_EVENT,
+  THERMAL_LEVEL,
+  IDLE_POWER_COLLAPSE,
+};
+
+class HWEventsInterface {
+ public:
+  virtual DisplayError Init(int display_type, HWEventHandler *event_handler,
+                            const std::vector<HWEvent> &event_list) = 0;
+  virtual DisplayError Deinit() = 0;
+  virtual DisplayError SetEventState(HWEvent event, bool enable, void *aux = nullptr) = 0;
+
+  static DisplayError Create(int display_type, HWEventHandler *event_handler,
+                             const std::vector<HWEvent> &event_list, HWEventsInterface **intf);
+  static DisplayError Destroy(HWEventsInterface *intf);
+
+ protected:
+  virtual ~HWEventsInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __HW_EVENTS_INTERFACE_H__
+
diff --git a/sdm845/sdm/libs/core/hw_info_interface.cpp b/sdm845/sdm/libs/core/hw_info_interface.cpp
new file mode 100644
index 0000000..1773fe5
--- /dev/null
+++ b/sdm845/sdm/libs/core/hw_info_interface.cpp
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2017, 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/utils.h>
+
+#include "hw_info_interface.h"
+#include "fb/hw_info.h"
+#ifdef COMPILE_DRM
+#include "drm/hw_info_drm.h"
+#endif
+
+#define __CLASS__ "HWInfoInterface"
+
+namespace sdm {
+
+DisplayError HWInfoInterface::Create(HWInfoInterface **intf) {
+  if (GetDriverType() == DriverType::FB) {
+    *intf = new HWInfo();
+  } else {
+#ifdef COMPILE_DRM
+    *intf = new HWInfoDRM();
+#endif
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWInfoInterface::Destroy(HWInfoInterface *intf) {
+  if (intf) {
+    delete intf;
+  }
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/hw_info_interface.h b/sdm845/sdm/libs/core/hw_info_interface.h
new file mode 100644
index 0000000..401c8bf
--- /dev/null
+++ b/sdm845/sdm/libs/core/hw_info_interface.h
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_INFO_INTERFACE_H__
+#define __HW_INFO_INTERFACE_H__
+
+#include <inttypes.h>
+#include <core/core_interface.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;
+  virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) = 0;
+
+ protected:
+  virtual ~HWInfoInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __HW_INFO_INTERFACE_H__
+
diff --git a/sdm845/sdm/libs/core/hw_interface.cpp b/sdm845/sdm/libs/core/hw_interface.cpp
new file mode 100644
index 0000000..a27c5f8
--- /dev/null
+++ b/sdm845/sdm/libs/core/hw_interface.cpp
@@ -0,0 +1,105 @@
+/*
+* Copyright (c) 2017, 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 <utils/utils.h>
+
+#include "hw_interface.h"
+#include "fb/hw_device.h"
+#include "fb/hw_primary.h"
+#include "fb/hw_hdmi.h"
+#include "fb/hw_virtual.h"
+#ifdef COMPILE_DRM
+#include "drm/hw_device_drm.h"
+#include "drm/hw_virtual_drm.h"
+#endif
+
+#define __CLASS__ "HWInterface"
+
+namespace sdm {
+
+DisplayError HWInterface::Create(DisplayType type, HWInfoInterface *hw_info_intf,
+                                 BufferSyncHandler *buffer_sync_handler,
+                                 BufferAllocator *buffer_allocator, HWInterface **intf) {
+  DisplayError error = kErrorNone;
+  HWInterface *hw = nullptr;
+  DriverType driver_type = GetDriverType();
+
+  switch (type) {
+    case kPrimary:
+      if (driver_type == DriverType::FB) {
+        hw = new HWPrimary(buffer_sync_handler, hw_info_intf);
+      } else {
+#ifdef COMPILE_DRM
+        hw = new HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf);
+#endif
+      }
+      break;
+    case kHDMI:
+      if (driver_type == DriverType::FB) {
+        hw = new HWHDMI(buffer_sync_handler, hw_info_intf);
+      } else {
+        return kErrorNotSupported;
+      }
+      break;
+    case kVirtual:
+      if (driver_type == DriverType::FB) {
+        hw = new HWVirtual(buffer_sync_handler,hw_info_intf);
+      } else {
+#ifdef COMPILE_DRM
+        hw = new HWVirtualDRM(buffer_sync_handler, buffer_allocator, hw_info_intf);
+#endif
+      }
+      break;
+    default:
+      DLOGE("Undefined display type");
+      return kErrorUndefined;
+  }
+
+  error = hw->Init();
+  if (error != kErrorNone) {
+    delete hw;
+    DLOGE("Init on HW Intf type %d failed", type);
+    return error;
+  }
+  *intf = hw;
+
+  return error;
+}
+
+DisplayError HWInterface::Destroy(HWInterface *intf) {
+  if (intf) {
+    intf->Deinit();
+    delete intf;
+  }
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/hw_interface.h b/sdm845/sdm/libs/core/hw_interface.h
new file mode 100644
index 0000000..5dbeb11
--- /dev/null
+++ b/sdm845/sdm/libs/core/hw_interface.h
@@ -0,0 +1,121 @@
+/*
+* Copyright (c) 2014 - 2017, 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/buffer_allocator.h>
+#include <core/buffer_sync_handler.h>
+#include <core/display_interface.h>
+#include <private/hw_info_types.h>
+#include <private/color_interface.h>
+#include <utils/constants.h>
+
+#include "hw_info_interface.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;
+  virtual void CECMessage(char *message) = 0;
+  virtual void IdlePowerCollapse() = 0;
+
+ protected:
+  virtual ~HWEventHandler() { }
+};
+
+class HWInterface {
+ public:
+  static DisplayError Create(DisplayType type, HWInfoInterface *hw_info_intf,
+                             BufferSyncHandler *buffer_sync_handler,
+                             BufferAllocator *buffer_allocator, HWInterface **intf);
+  static DisplayError Destroy(HWInterface *intf);
+
+  virtual DisplayError Init() = 0;
+  virtual DisplayError Deinit() = 0;
+  virtual DisplayError GetActiveConfig(uint32_t *active_config) = 0;
+  virtual DisplayError GetNumDisplayAttributes(uint32_t *count) = 0;
+  virtual DisplayError GetDisplayAttributes(uint32_t index,
+                                            HWDisplayAttributes *display_attributes) = 0;
+  virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info) = 0;
+  virtual DisplayError SetDisplayAttributes(uint32_t index) = 0;
+  virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes) = 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;
+  virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers) = 0;
+  virtual DisplayError SetPPFeatures(PPFeaturesConfig *feature_list) = 0;
+  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;
+  virtual DisplayError SetPanelBrightness(int level) = 0;
+  virtual DisplayError CachePanelBrightness(int level) = 0;
+  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;
+  virtual DisplayError SetCursorPosition(HWLayers *hw_layers, int x, int y) = 0;
+  virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) = 0;
+  virtual DisplayError GetPanelBrightness(int *level) = 0;
+  virtual DisplayError SetAutoRefresh(bool enable) = 0;
+  virtual DisplayError SetS3DMode(HWS3DMode s3d_mode) = 0;
+  virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info) = 0;
+  virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) = 0;
+  virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes) = 0;
+
+ protected:
+  virtual ~HWInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __HW_INTERFACE_H__
+
diff --git a/sdm845/sdm/libs/core/resource_default.cpp b/sdm845/sdm/libs/core/resource_default.cpp
new file mode 100644
index 0000000..2d74941
--- /dev/null
+++ b/sdm845/sdm/libs/core/resource_default.cpp
@@ -0,0 +1,944 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <math.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/rect.h>
+#include <utils/formats.h>
+#include <utils/sys.h>
+#include <dlfcn.h>
+#include <algorithm>
+
+#include "resource_default.h"
+
+#define __CLASS__ "ResourceDefault"
+
+namespace sdm {
+
+DisplayError ResourceDefault::CreateResourceDefault(const HWResourceInfo &hw_resource_info,
+                                                    ResourceInterface **resource_intf) {
+  DisplayError error = kErrorNone;
+
+  ResourceDefault *resource_default = new ResourceDefault(hw_resource_info);
+  if (!resource_default) {
+    return kErrorNone;
+  }
+
+  error = resource_default->Init();
+  if (error != kErrorNone) {
+    delete resource_default;
+  }
+
+  *resource_intf = resource_default;
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::DestroyResourceDefault(ResourceInterface *resource_intf) {
+  ResourceDefault *resource_default = static_cast<ResourceDefault *>(resource_intf);
+
+  resource_default->Deinit();
+  delete resource_default;
+
+  return kErrorNone;
+}
+
+ResourceDefault::ResourceDefault(const HWResourceInfo &hw_res_info)
+  : hw_res_info_(hw_res_info) {
+}
+
+DisplayError ResourceDefault::Init() {
+  DisplayError error = kErrorNone;
+
+  num_pipe_ = hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe + hw_res_info_.num_dma_pipe;
+
+  if (!num_pipe_) {
+    DLOGE("Number of H/W pipes is Zero!");
+    return kErrorParameters;
+  }
+
+  src_pipes_.resize(num_pipe_);
+
+  // Priority order of pipes: VIG, RGB, DMA
+  uint32_t vig_index = 0;
+  uint32_t rgb_index = hw_res_info_.num_vig_pipe;
+  uint32_t dma_index = rgb_index + hw_res_info_.num_rgb_pipe;
+
+  for (uint32_t i = 0; i < num_pipe_; i++) {
+    const HWPipeCaps &pipe_caps = hw_res_info_.hw_pipes.at(i);
+    if (pipe_caps.type == kPipeTypeVIG) {
+      src_pipes_[vig_index].type = kPipeTypeVIG;
+      src_pipes_[vig_index].index = i;
+      src_pipes_[vig_index].mdss_pipe_id = pipe_caps.id;
+      vig_index++;
+    } else if (pipe_caps.type == kPipeTypeRGB) {
+      src_pipes_[rgb_index].type = kPipeTypeRGB;
+      src_pipes_[rgb_index].index = i;
+      src_pipes_[rgb_index].mdss_pipe_id = pipe_caps.id;
+      rgb_index++;
+    } else if (pipe_caps.type == kPipeTypeDMA) {
+      src_pipes_[dma_index].type = kPipeTypeDMA;
+      src_pipes_[dma_index].index = i;
+      src_pipes_[dma_index].mdss_pipe_id = pipe_caps.id;
+      dma_index++;
+    }
+  }
+
+  for (uint32_t i = 0; i < num_pipe_; i++) {
+    src_pipes_[i].priority = INT(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;
+  }
+
+  // TODO(user): clean it up, query from driver for initial pipe status.
+#ifndef SDM_VIRTUAL_DRIVER
+  rgb_index = hw_res_info_.num_vig_pipe;
+  src_pipes_[rgb_index].owner = kPipeOwnerKernelMode;
+  src_pipes_[rgb_index + 1].owner = kPipeOwnerKernelMode;
+#endif
+
+  return error;
+}
+
+DisplayError ResourceDefault::Deinit() {
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::RegisterDisplay(DisplayType type,
+                                              const HWDisplayAttributes &display_attributes,
+                                              const HWPanelInfo &hw_panel_info,
+                                              const HWMixerAttributes &mixer_attributes,
+                                              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 = display_attributes;
+  display_resource_ctx->hw_block_id = hw_block_id;
+  display_resource_ctx->mixer_attributes = mixer_attributes;
+
+  *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;
+}
+
+DisplayError ResourceDefault::ReconfigureDisplay(Handle display_ctx,
+                                                 const HWDisplayAttributes &display_attributes,
+                                                 const HWPanelInfo &hw_panel_info,
+                                                 const HWMixerAttributes &mixer_attributes) {
+  SCOPE_LOCK(locker_);
+
+  DisplayResourceContext *display_resource_ctx =
+                          reinterpret_cast<DisplayResourceContext *>(display_ctx);
+
+  display_resource_ctx->display_attributes = display_attributes;
+  display_resource_ctx->mixer_attributes = mixer_attributes;
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::Start(Handle display_ctx) {
+  locker_.Lock();
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::Stop(Handle display_ctx) {
+  locker_.Unlock();
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::Prepare(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.hw_layers.size() > 1) {
+    DLOGV_IF(kTagResources, "More than one FB layers");
+    return kErrorResources;
+  }
+
+  const Layer &layer = layer_info.hw_layers.at(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 = num_pipe_;
+  uint32_t right_index = num_pipe_;
+  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
+    std::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::Commit(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;
+
+  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;
+      }
+    }
+  }
+
+  if (hw_layers->info.sync_handle >= 0)
+    Sys::close_(hw_layers->info.sync_handle);
+
+  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::SearchPipe(HWBlockType hw_block_id, SourcePipe *src_pipes,
+                                uint32_t num_pipe) {
+  uint32_t index = num_pipe_;
+  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 = &src_pipes_[0];
+    num_pipe = hw_res_info_.num_vig_pipe;
+    break;
+  case kPipeTypeRGB:
+    src_pipes = &src_pipes_[hw_res_info_.num_vig_pipe];
+    num_pipe = hw_res_info_.num_rgb_pipe;
+    break;
+  case kPipeTypeDMA:
+  default:
+    src_pipes = &src_pipes_[hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe];
+    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 = num_pipe_;
+
+  // 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) {
+  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;
+
+  // Layer cannot qualify for SrcSplit if source or destination width exceeds max pipe width.
+  if ((src_width > hw_res_info_.max_pipe_width) || (dst_width > hw_res_info_.max_pipe_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) {
+  HWMixerAttributes &mixer_attributes = display_resource_ctx->mixer_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(mixer_attributes.split_left);
+  scissor_left.bottom = FLOAT(mixer_attributes.height);
+
+  scissor_right.left = FLOAT(mixer_attributes.split_left);
+  scissor_right.top = 0.0f;
+  scissor_right.right = FLOAT(mixer_attributes.width);
+  scissor_right.bottom = FLOAT(mixer_attributes.height);
+
+  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) {
+  HWLayersInfo &layer_info = hw_layers->info;
+  DisplayError error = kErrorNone;
+  const Layer &layer = layer_info.hw_layers.at(0);
+
+  error = ValidateLayerParams(&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;
+  }
+
+  BufferLayout layout = GetBufferLayout(layer.input_buffer.format);
+  error = ValidateScaling(src_rect, dst_rect, false /*rotated90 */, layout,
+                          false /* use_rotator_downscale */);
+  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::ValidateLayerParams(const Layer *layer) {
+  const LayerRect &src = layer->src_rect;
+  const LayerRect &dst = layer->dst_rect;
+  const LayerBuffer &input_buffer = layer->input_buffer;
+
+  if (input_buffer.format == kFormatInvalid) {
+    DLOGV_IF(kTagResources, "Invalid input buffer format %d", input_buffer.format);
+    return kErrorNotSupported;
+  }
+
+  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) != 0.0f) ||
+       (src.top - roundf(src.top) != 0.0f) ||
+       (src.right - roundf(src.right) != 0.0f) ||
+       (src.bottom - roundf(src.bottom) != 0.0f))) {
+    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, LayerBufferFormat format) {
+  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;
+  }
+
+  BufferLayout layout = GetBufferLayout(format);
+  error = ValidateScaling(src_rect, dst_rect, false /* rotated90 */, layout,
+                          false /* use_rotator_downscale */);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::ValidateScaling(const LayerRect &crop, const LayerRect &dst,
+                                              bool rotate90, BufferLayout layout,
+                                              bool use_rotator_downscale) {
+  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, (layout != kLinear));
+  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, bool ubwc_tiled) {
+  if ((UINT32(scale_x) > 1) || (UINT32(scale_y) > 1)) {
+    float max_scale_down = FLOAT(hw_res_info_.max_scale_down);
+
+    // MDP H/W cannot apply decimation on UBWC tiled framebuffer
+    if (!ubwc_tiled && 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, layer->input_buffer.format);
+  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, layer->input_buffer.format);
+  }
+
+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;
+}
+
+DisplayError ResourceDefault::ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers,
+                                                     int x, int y) {
+  return kErrorNotSupported;
+}
+
+DisplayError ResourceDefault::SetMaxBandwidthMode(HWBwModes mode) {
+  return kErrorNotSupported;
+}
+
+DisplayError ResourceDefault::GetScaleLutConfig(HWScaleLutInfo *lut_info) {
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::SetDetailEnhancerData(Handle display_ctx,
+                                                    const DisplayDetailEnhancerData &de_data) {
+  return kErrorNotSupported;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/resource_default.h b/sdm845/sdm/libs/core/resource_default.h
new file mode 100644
index 0000000..f835410
--- /dev/null
+++ b/sdm845/sdm/libs/core/resource_default.h
@@ -0,0 +1,149 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <vector>
+
+#include "hw_interface.h"
+
+namespace sdm {
+
+class ResourceDefault : public ResourceInterface {
+ public:
+  static DisplayError CreateResourceDefault(const HWResourceInfo &hw_resource_info,
+                                            ResourceInterface **resource_intf);
+  static DisplayError DestroyResourceDefault(ResourceInterface *resource_intf);
+  virtual DisplayError RegisterDisplay(DisplayType type,
+                                       const HWDisplayAttributes &display_attributes,
+                                       const HWPanelInfo &hw_panel_info,
+                                       const HWMixerAttributes &mixer_attributes,
+                                       Handle *display_ctx);
+  virtual DisplayError UnregisterDisplay(Handle display_ctx);
+  virtual DisplayError ReconfigureDisplay(Handle display_ctx,
+                                          const HWDisplayAttributes &display_attributes,
+                                          const HWPanelInfo &hw_panel_info,
+                                          const HWMixerAttributes &mixer_attributes);
+  virtual DisplayError Start(Handle display_ctx);
+  virtual DisplayError Stop(Handle display_ctx);
+  virtual DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
+  virtual DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
+  virtual DisplayError Commit(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,
+                                       BufferLayout layout, bool use_rotator_downscale);
+  DisplayError ValidateCursorConfig(Handle display_ctx, const Layer *layer, bool is_top);
+  DisplayError ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers, int x, int y);
+  DisplayError SetMaxBandwidthMode(HWBwModes mode);
+  virtual DisplayError SetDetailEnhancerData(Handle display_ctx,
+                                             const DisplayDetailEnhancerData &de_data);
+  virtual DisplayError Perform(int cmd, ...) { return kErrorNone; }
+
+ private:
+  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 = 16,
+  };
+
+  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(0),
+                  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;
+    HWMixerAttributes mixer_attributes;
+
+    DisplayResourceContext() : hw_block_id(kHWBlockMax), frame_count(0) { }
+  };
+
+  struct HWBlockContext {
+    bool is_in_use;
+    HWBlockContext() : is_in_use(false) { }
+  };
+
+  explicit ResourceDefault(const HWResourceInfo &hw_res_info);
+  DisplayError Init();
+  DisplayError Deinit();
+  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 ValidateLayerParams(const Layer *layer);
+  DisplayError ValidateDimensions(const LayerRect &crop, const LayerRect &dst);
+  DisplayError ValidatePipeParams(HWPipeInfo *pipe_info, LayerBufferFormat format);
+  DisplayError ValidateDownScaling(float scale_x, float scale_y, bool ubwc_tiled);
+  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);
+  DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info);
+
+  Locker locker_;
+  HWResourceInfo hw_res_info_;
+  HWBlockContext hw_block_ctx_[kHWBlockMax];
+  std::vector<SourcePipe> src_pipes_;
+  uint32_t num_pipe_ = 0;
+};
+
+}  // namespace sdm
+
+#endif  // __RESOURCE_DEFAULT_H__
+
diff --git a/sdm845/sdm/libs/core/strategy.cpp b/sdm845/sdm/libs/core/strategy.cpp
new file mode 100644
index 0000000..8398bbd
--- /dev/null
+++ b/sdm845/sdm/libs/core/strategy.cpp
@@ -0,0 +1,265 @@
+/*
+* Copyright (c) 2014 - 2017, 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"
+#include "utils/rect.h"
+
+#define __CLASS__ "Strategy"
+
+namespace sdm {
+
+Strategy::Strategy(ExtensionInterface *extension_intf, BufferAllocator *buffer_allocator,
+                   DisplayType type,
+                   const HWResourceInfo &hw_resource_info, const HWPanelInfo &hw_panel_info,
+                   const HWMixerAttributes &mixer_attributes,
+                   const HWDisplayAttributes &display_attributes,
+                   const DisplayConfigVariableInfo &fb_config)
+  : extension_intf_(extension_intf), display_type_(type), hw_resource_info_(hw_resource_info),
+    hw_panel_info_(hw_panel_info), mixer_attributes_(mixer_attributes),
+    display_attributes_(display_attributes), fb_config_(fb_config),
+    buffer_allocator_(buffer_allocator) {
+}
+
+DisplayError Strategy::Init() {
+  DisplayError error = kErrorNone;
+
+  if (extension_intf_) {
+    error = extension_intf_->CreateStrategyExtn(display_type_, buffer_allocator_, hw_resource_info_,
+                                                hw_panel_info_, mixer_attributes_, fb_config_,
+                                                &strategy_intf_);
+    if (error != kErrorNone) {
+      DLOGE("Failed to create strategy");
+      return error;
+    }
+
+    error = extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_, hw_panel_info_,
+                                                 mixer_attributes_, display_attributes_, fb_config_,
+                                                 &partial_update_intf_);
+  }
+
+  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,
+                             const PUConstraints &pu_constraints) {
+  DisplayError error = kErrorNone;
+
+  hw_layers_info_ = hw_layers_info;
+  extn_start_success_ = false;
+  tried_default_ = false;
+
+  if (!disable_gpu_comp_ && !hw_layers_info_->gpu_target_index) {
+    DLOGE("GPU composition is enabled and GPU target buffer not provided.");
+    return kErrorNotSupported;
+  }
+
+  if (partial_update_intf_) {
+    partial_update_intf_->Start(pu_constraints);
+  }
+  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 (strategy_intf_) {
+    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;
+    }
+  }
+
+  // Do not fallback to GPU if GPU comp is disabled.
+  if (disable_gpu_comp_) {
+    return kErrorNotSupported;
+  }
+
+  // Default composition is already tried.
+  if (tried_default_) {
+    return kErrorUndefined;
+  }
+
+  // Mark all application layers for GPU composition. Find GPU target buffer and store its index for
+  // programming the hardware.
+  LayerStack *layer_stack = hw_layers_info_->stack;
+  for (uint32_t i = 0; i < hw_layers_info_->app_layer_count; i++) {
+    layer_stack->layers.at(i)->composition = kCompositionGPU;
+    layer_stack->layers.at(i)->request.flags.request_flags = 0;  // Reset layer request
+  }
+
+  if (!extn_start_success_) {
+    // When mixer resolution and panel resolutions are same (1600x2560) and FB resolution is
+    // 1080x1920 FB_Target destination coordinates(mapped to FB resolution 1080x1920) need to
+    // be mapped to destination coordinates of mixer resolution(1600x2560).
+    Layer *gpu_target_layer = layer_stack->layers.at(hw_layers_info_->gpu_target_index);
+    float layer_mixer_width = FLOAT(mixer_attributes_.width);
+    float layer_mixer_height = FLOAT(mixer_attributes_.height);
+    float fb_width = FLOAT(fb_config_.x_pixels);
+    float fb_height = FLOAT(fb_config_.y_pixels);
+    LayerRect src_domain = (LayerRect){0.0f, 0.0f, fb_width, fb_height};
+    LayerRect dst_domain = (LayerRect){0.0f, 0.0f, layer_mixer_width, layer_mixer_height};
+
+    Layer layer = *gpu_target_layer;
+    hw_layers_info_->index[0] = hw_layers_info_->gpu_target_index;
+    MapRect(src_domain, dst_domain, layer.dst_rect, &layer.dst_rect);
+    hw_layers_info_->hw_layers.clear();
+    hw_layers_info_->hw_layers.push_back(layer);
+  }
+
+  tried_default_ = true;
+
+  return kErrorNone;
+}
+
+void Strategy::GenerateROI() {
+  bool split_display = false;
+
+  if (partial_update_intf_ && partial_update_intf_->GenerateROI(hw_layers_info_) == kErrorNone) {
+    return;
+  }
+
+  float layer_mixer_width = mixer_attributes_.width;
+  float layer_mixer_height = mixer_attributes_.height;
+
+  if (!hw_resource_info_.is_src_split && display_attributes_.is_device_split) {
+    split_display = true;
+  }
+
+  hw_layers_info_->left_frame_roi = {};
+  hw_layers_info_->right_frame_roi = {};
+
+  if (split_display) {
+    float left_split = FLOAT(mixer_attributes_.split_left);
+    hw_layers_info_->left_frame_roi.push_back(LayerRect(0.0f, 0.0f,
+                                left_split, layer_mixer_height));
+    hw_layers_info_->right_frame_roi.push_back(LayerRect(left_split,
+                                0.0f, layer_mixer_width, layer_mixer_height));
+  } else {
+    hw_layers_info_->left_frame_roi.push_back(LayerRect(0.0f, 0.0f,
+                                layer_mixer_width, layer_mixer_height));
+    hw_layers_info_->right_frame_roi.push_back(LayerRect(0.0f, 0.0f, 0.0f, 0.0f));
+  }
+}
+
+DisplayError Strategy::Reconfigure(const HWPanelInfo &hw_panel_info,
+                         const HWDisplayAttributes &display_attributes,
+                         const HWMixerAttributes &mixer_attributes,
+                         const DisplayConfigVariableInfo &fb_config) {
+  DisplayError error = kErrorNone;
+
+  if (!extension_intf_) {
+    return kErrorNone;
+  }
+
+  // TODO(user): PU Intf will not be created for video mode panels, hence re-evaluate if
+  // reconfigure is needed.
+  if (partial_update_intf_) {
+    extension_intf_->DestroyPartialUpdate(partial_update_intf_);
+    partial_update_intf_ = NULL;
+  }
+
+  extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_, hw_panel_info,
+                                       mixer_attributes, display_attributes, fb_config,
+                                       &partial_update_intf_);
+
+  error = strategy_intf_->Reconfigure(hw_panel_info, hw_resource_info_, mixer_attributes,
+                                      fb_config);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  hw_panel_info_ = hw_panel_info;
+  display_attributes_ = display_attributes;
+  mixer_attributes_ = mixer_attributes;
+  fb_config_ = fb_config;
+
+  return kErrorNone;
+}
+
+DisplayError Strategy::SetCompositionState(LayerComposition composition_type, bool enable) {
+  DLOGI("composition type = %d, enable = %d", composition_type, enable);
+
+  if (composition_type == kCompositionGPU) {
+    disable_gpu_comp_ = !enable;
+  }
+
+  if (strategy_intf_) {
+    return strategy_intf_->SetCompositionState(composition_type, enable);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError Strategy::Purge() {
+  if (strategy_intf_) {
+    return strategy_intf_->Purge();
+  }
+
+  return kErrorNone;
+}
+
+DisplayError Strategy::SetIdleTimeoutMs(uint32_t active_ms) {
+  if (strategy_intf_) {
+    return strategy_intf_->SetIdleTimeoutMs(active_ms);
+  }
+
+  return kErrorNotSupported;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/core/strategy.h b/sdm845/sdm/libs/core/strategy.h
new file mode 100644
index 0000000..f05f66b
--- /dev/null
+++ b/sdm845/sdm/libs/core/strategy.h
@@ -0,0 +1,79 @@
+/*
+* Copyright (c) 2014 - 2017, 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>
+#include <core/buffer_allocator.h>
+
+namespace sdm {
+
+class Strategy {
+ public:
+  Strategy(ExtensionInterface *extension_intf, BufferAllocator *buffer_allocator,
+           DisplayType type,
+           const HWResourceInfo &hw_resource_info, const HWPanelInfo &hw_panel_info,
+           const HWMixerAttributes &mixer_attributes, const HWDisplayAttributes &display_attributes,
+           const DisplayConfigVariableInfo &fb_config);
+
+  DisplayError Init();
+  DisplayError Deinit();
+
+  DisplayError Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts,
+                     const PUConstraints &pu_constraints);
+  DisplayError GetNextStrategy(StrategyConstraints *constraints);
+  DisplayError Stop();
+  DisplayError Reconfigure(const HWPanelInfo &hw_panel_info,
+                           const HWDisplayAttributes &hw_display_attributes,
+                           const HWMixerAttributes &mixer_attributes,
+                           const DisplayConfigVariableInfo &fb_config);
+  DisplayError SetCompositionState(LayerComposition composition_type, bool enable);
+  DisplayError Purge();
+  DisplayError SetIdleTimeoutMs(uint32_t active_ms);
+
+ private:
+  void GenerateROI();
+
+  ExtensionInterface *extension_intf_ = NULL;
+  StrategyInterface *strategy_intf_ = NULL;
+  PartialUpdateInterface *partial_update_intf_ = NULL;
+  DisplayType display_type_;
+  HWResourceInfo hw_resource_info_;
+  HWPanelInfo hw_panel_info_;
+  HWLayersInfo *hw_layers_info_ = NULL;
+  HWMixerAttributes mixer_attributes_ = {};
+  HWDisplayAttributes display_attributes_ = {};
+  DisplayConfigVariableInfo fb_config_ = {};
+  bool extn_start_success_ = false;
+  bool tried_default_ = false;
+  bool disable_gpu_comp_ = false;
+  BufferAllocator *buffer_allocator_ = NULL;
+};
+
+}  // namespace sdm
+
+#endif  // __STRATEGY_H__
+
diff --git a/sdm845/sdm/libs/hwc/Android.mk b/sdm845/sdm/libs/hwc/Android.mk
new file mode 100644
index 0000000..a2142e3
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/Android.mk
@@ -0,0 +1,39 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/../../../common.mk
+ifeq ($(use_hwc2),false)
+
+LOCAL_MODULE                  := hwcomposer.$(TARGET_BOARD_PLATFORM)
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_RELATIVE_PATH    := hw
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes)
+LOCAL_HEADER_LIBRARIES        := display_headers
+
+LOCAL_CFLAGS                  := $(common_flags) -Wno-missing-field-initializers -Wno-unused-parameter \
+                                 -std=c++11 -fcolor-diagnostics -Wno-sign-conversion -DLOG_TAG=\"SDM\"
+LOCAL_CLANG                   := true
+
+LOCAL_SHARED_LIBRARIES        := libsdmcore libqservice libbinder libhardware libhardware_legacy \
+                                 libutils libcutils libsync libmemalloc libqdutils libdl \
+                                 libpowermanager libsdmutils libgpu_tonemapper  libc++ liblog \
+                                 libdrmutils libui
+
+LOCAL_SRC_FILES               := hwc_session.cpp \
+                                 hwc_display.cpp \
+                                 hwc_display_null.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 \
+                                 hwc_color_manager.cpp \
+                                 blit_engine_c2d.cpp \
+                                 cpuhint.cpp \
+                                 hwc_tonemapper.cpp \
+                                 hwc_socket_handler.cpp \
+                                 hwc_display_external_test.cpp
+
+include $(BUILD_SHARED_LIBRARY)
+endif
diff --git a/sdm845/sdm/libs/hwc/blit_engine.h b/sdm845/sdm/libs/hwc/blit_engine.h
new file mode 100644
index 0000000..6fa9733
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/blit_engine.h
@@ -0,0 +1,66 @@
+/*
+* 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.
+*/
+
+/*! @file blit_engine.h
+  @brief Interface file for Blit based compositior.
+
+  @details The client can use this interface to get the blit composition done
+
+*/
+
+#ifndef __BLIT_ENGINE_H__
+#define __BLIT_ENGINE_H__
+
+namespace sdm {
+
+/*! @brief Blit Engine implemented by the client
+
+  @details This class declares prototype for BlitEngine Interface which must be
+  implemented by the client. HWC will use this interface to use a Blit engine to get the
+  composition done.
+
+*/
+class BlitEngine {
+ public:
+  BlitEngine() { }
+  virtual ~BlitEngine() { }
+
+  virtual int Init() = 0;
+  virtual void DeInit() = 0;
+  virtual int Prepare(LayerStack *layer_stack) = 0;
+  virtual int PreCommit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) = 0;
+  virtual int Commit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) = 0;
+  virtual void PostCommit(LayerStack *layer_stack) = 0;
+  virtual bool BlitActive() = 0;
+  virtual void SetFrameDumpConfig(uint32_t count) = 0;
+};
+
+}  // namespace sdm
+
+#endif  // __BLIT_ENGINE_H__
diff --git a/sdm845/sdm/libs/hwc/blit_engine_c2d.cpp b/sdm845/sdm/libs/hwc/blit_engine_c2d.cpp
new file mode 100644
index 0000000..4efe2f1
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/blit_engine_c2d.cpp
@@ -0,0 +1,608 @@
+/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*  * Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above
+*    copyright notice, this list of conditions and the following
+*    disclaimer in the documentation and/or other materials provided
+*    with the distribution.
+*  * Neither the name of The Linux Foundation nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+* Portions formerly licensed under Apache License, Version 2.0, are re licensed
+* under section 4 of Apache License, Version 2.0.
+
+* Copyright (C) 2010 The Android Open Source Project
+
+* Not a Contribution.
+
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+
+* http://www.apache.org/licenses/LICENSE-2.0
+
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <hardware/hardware.h>
+#include <sync/sync.h>
+#include <copybit.h>
+#include <memalloc.h>
+#include <alloc_controller.h>
+#include <gr.h>
+
+#include <utils/constants.h>
+#include <utils/rect.h>
+#include <utils/formats.h>
+#include <algorithm>
+
+#include "blit_engine_c2d.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "BlitEngineC2D"
+
+// TODO(user): Remove pragma after fixing sign conversion errors
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wsign-conversion"
+#endif
+
+namespace sdm {
+
+
+BlitEngineC2d::RegionIterator::RegionIterator(LayerRectArray rect) {
+  rect_array = rect;
+  r.end = INT(rect.count);
+  r.current = 0;
+  this->next = iterate;
+}
+
+int BlitEngineC2d::RegionIterator::iterate(copybit_region_t const *self, copybit_rect_t *rect) {
+  if (!self || !rect) {
+    DLOGE("iterate invalid parameters");
+    return 0;
+  }
+
+  RegionIterator const *me = static_cast<RegionIterator const*>(self);
+  if (me->r.current != me->r.end) {
+    rect->l = INT(me->rect_array.rect[me->r.current].left);
+    rect->t = INT(me->rect_array.rect[me->r.current].top);
+    rect->r = INT(me->rect_array.rect[me->r.current].right);
+    rect->b = INT(me->rect_array.rect[me->r.current].bottom);
+    me->r.current++;
+    return 1;
+  }
+  return 0;
+}
+
+BlitEngineC2d::BlitEngineC2d() {
+  for (uint32_t i = 0; i < kNumBlitTargetBuffers; i++) {
+    blit_target_buffer_[i] = NULL;
+    release_fence_fd_[i] = -1;
+  }
+}
+
+BlitEngineC2d::~BlitEngineC2d() {
+  if (blit_engine_c2d_) {
+    copybit_close(blit_engine_c2d_);
+    blit_engine_c2d_ = NULL;
+  }
+  FreeBlitTargetBuffers();
+}
+
+int BlitEngineC2d::Init() {
+  hw_module_t const *module;
+  if (hw_get_module("copybit", &module) == 0) {
+    if (copybit_open(module, &blit_engine_c2d_) < 0) {
+      DLOGI("CopyBitC2D Open failed.");
+      return -1;
+    }
+    DLOGI("Opened Copybit Module");
+  } else {
+    DLOGI("Copybit HW Module not found");
+    return -1;
+  }
+
+  return 0;
+}
+
+void BlitEngineC2d::DeInit() {
+  FreeBlitTargetBuffers();
+  if (blit_engine_c2d_) {
+    copybit_close(blit_engine_c2d_);
+    blit_engine_c2d_ = NULL;
+  }
+}
+
+int BlitEngineC2d::AllocateBlitTargetBuffers(uint32_t width, uint32_t height, uint32_t format,
+                                             uint32_t usage) {
+  int status = 0;
+  if (width <= 0 || height <= 0) {
+    return false;
+  }
+
+  if (blit_target_buffer_[0]) {
+    // Free and reallocate the buffers if the w/h changes
+    if (INT(width) != blit_target_buffer_[0]->width ||
+        INT(height) != blit_target_buffer_[0]->height) {
+      FreeBlitTargetBuffers();
+    }
+  }
+
+  for (uint32_t i = 0; i < kNumBlitTargetBuffers; i++) {
+    if (blit_target_buffer_[i] == NULL) {
+      status = alloc_buffer(&blit_target_buffer_[i], width, height, format, usage);
+    }
+    if (status < 0) {
+      DLOGE("Allocation of Blit target Buffer failed");
+      FreeBlitTargetBuffers();
+      break;
+    }
+  }
+
+  return status;
+}
+
+void BlitEngineC2d::FreeBlitTargetBuffers() {
+  for (uint32_t i = 0; i < kNumBlitTargetBuffers; i++) {
+    private_handle_t **target_buffer = &blit_target_buffer_[i];
+    if (*target_buffer) {
+      // Free the valid fence
+      if (release_fence_fd_[i] >= 0) {
+        close(release_fence_fd_[i]);
+        release_fence_fd_[i] = -1;
+      }
+      free_buffer(*target_buffer);
+      *target_buffer = NULL;
+    }
+  }
+}
+
+int BlitEngineC2d::ClearTargetBuffer(private_handle_t* hnd, const LayerRect& rect) {
+  int status = 0;
+  copybit_rect_t clear_rect = {INT(rect.left), INT(rect.top), INT(rect.right), INT(rect.bottom)};
+
+  copybit_image_t buffer;
+  buffer.w = ALIGN((hnd->width), 32);
+  buffer.h = hnd->height;
+  buffer.format = hnd->format;
+  buffer.base = reinterpret_cast<void *>(hnd->base);
+  buffer.handle = reinterpret_cast<native_handle_t *>(hnd);
+  int dst_format_mode = COPYBIT_LINEAR;
+  if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+    dst_format_mode = COPYBIT_UBWC_COMPRESSED;
+  }
+  blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_DST_FORMAT_MODE, dst_format_mode);
+
+  status = blit_engine_c2d_->clear(blit_engine_c2d_, &buffer, &clear_rect);
+  return status;
+}
+
+void BlitEngineC2d::PostCommit(LayerStack *layer_stack) {
+  int fence_fd = -1;
+  uint32_t count = 0;
+  int fd = -1;
+
+  for (uint32_t i = blit_target_start_index_-2; (i > 0) && (count < num_blit_target_); i--) {
+    Layer *layer = layer_stack->layers.at(i);
+    LayerBuffer &layer_buffer = layer->input_buffer;
+    if (layer->composition == kCompositionBlit) {
+      int index = blit_target_start_index_ + count;
+      layer_buffer.release_fence_fd =
+        layer_stack->layers.at(index)->input_buffer.release_fence_fd;
+      fence_fd = layer_buffer.release_fence_fd;
+      close(layer_buffer.acquire_fence_fd);
+      layer_buffer.acquire_fence_fd = -1;
+      layer_stack->layers.at(index)->input_buffer.release_fence_fd = -1;
+      fd = layer_stack->layers.at(index)->input_buffer.acquire_fence_fd;
+      layer_stack->layers.at(index)->input_buffer.acquire_fence_fd = -1;
+      count++;
+    }
+  }
+
+  if (fd >= 0) {
+    // Close the C2D fence FD
+    close(fd);
+  }
+  SetReleaseFence(fence_fd);
+}
+
+// Sync wait to close the previous fd
+void BlitEngineC2d::SetReleaseFence(int fd) {
+  if (release_fence_fd_[current_blit_target_index_] >= 0) {
+    int ret = -1;
+    ret = sync_wait(release_fence_fd_[current_blit_target_index_], 1000);
+    if (ret < 0) {
+      DLOGE("sync_wait error! errno = %d, err str = %s", errno, strerror(errno));
+    }
+    close(release_fence_fd_[current_blit_target_index_]);
+  }
+  release_fence_fd_[current_blit_target_index_] = dup(fd);
+}
+
+bool BlitEngineC2d::BlitActive() {
+  return blit_active_;
+}
+
+void BlitEngineC2d::SetFrameDumpConfig(uint32_t count) {
+  dump_frame_count_ = count;
+  dump_frame_index_ = 0;
+}
+
+int BlitEngineC2d::Prepare(LayerStack *layer_stack) {
+  blit_target_start_index_ = 0;
+
+  uint32_t layer_count = UINT32(layer_stack->layers.size());
+  uint32_t gpu_target_index = layer_count - 1;  // default assumption
+  uint32_t i = 0;
+
+  for (; i < layer_count; i++) {
+    Layer *layer = layer_stack->layers.at(i);
+
+    // No 10 bit support for C2D
+    if (Is10BitFormat(layer->input_buffer.format)) {
+      return -1;
+    }
+
+    if (layer->composition == kCompositionGPUTarget) {
+      // Need FBT size for allocating buffers
+      gpu_target_index = i;
+      break;
+    }
+  }
+
+  if ((layer_count - 1) == gpu_target_index) {
+    // No blit target layer
+    return -1;
+  }
+
+  blit_target_start_index_ = ++i;
+  num_blit_target_ = layer_count - blit_target_start_index_;
+
+  LayerBuffer &layer_buffer = layer_stack->layers.at(gpu_target_index)->input_buffer;
+  int fbwidth = INT(layer_buffer.unaligned_width);
+  int fbheight = INT(layer_buffer.unaligned_height);
+  if ((fbwidth < 0) || (fbheight < 0)) {
+    return -1;
+  }
+
+  current_blit_target_index_ = (current_blit_target_index_ + 1) % kNumBlitTargetBuffers;
+  int k = blit_target_start_index_;
+
+  for (uint32_t j = 0; j < num_blit_target_; j++, k++) {
+    Layer *layer = layer_stack->layers.at(k);
+    LayerBuffer &layer_buffer = layer->input_buffer;
+    int aligned_w = 0;
+    int aligned_h = 0;
+
+    // Set the buffer height and width
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(fbwidth, fbheight/3,
+                   INT(HAL_PIXEL_FORMAT_RGBA_8888), 0, aligned_w, aligned_h);
+    layer_buffer.width = aligned_w;
+    layer_buffer.height = aligned_h;
+    layer_buffer.unaligned_width = fbwidth;
+    layer_buffer.unaligned_height = fbheight/3;
+
+    layer->plane_alpha = 0xFF;
+    layer->blending = kBlendingOpaque;
+    layer->composition = kCompositionBlitTarget;
+    layer->frame_rate = layer_stack->layers.at(gpu_target_index)->frame_rate;
+  }
+
+  return 0;
+}
+
+int BlitEngineC2d::PreCommit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) {
+  int status = 0;
+  uint32_t num_app_layers = (uint32_t) content_list->numHwLayers-1;
+  int target_width = 0;
+  int target_height = 0;
+  int target_aligned_width = 0;
+  int target_aligned_height = 0;
+  uint32_t processed_blit = 0;
+  LayerRect dst_rects[kMaxBlitTargetLayers];
+  bool blit_needed = false;
+  uint32_t usage = 0;
+
+  if (!num_app_layers) {
+    return -1;
+  }
+
+  for (uint32_t i = num_app_layers-1; (i > 0) && (processed_blit < num_blit_target_); i--) {
+    Layer *layer = layer_stack->layers.at(i);
+    if (layer->composition != kCompositionBlit) {
+      continue;
+    }
+    blit_needed = true;
+    layer_stack->flags.attributes_changed = true;
+
+    Layer *blit_layer = layer_stack->layers.at(blit_target_start_index_ + processed_blit);
+    LayerRect &blit_src_rect = blit_layer->src_rect;
+    int width = INT(layer->dst_rect.right - layer->dst_rect.left);
+    int height = INT(layer->dst_rect.bottom - layer->dst_rect.top);
+    int aligned_w = 0;
+    int aligned_h = 0;
+    usage = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | GRALLOC_USAGE_HW_TEXTURE;
+    if (blit_engine_c2d_->get(blit_engine_c2d_, COPYBIT_UBWC_SUPPORT) > 0) {
+      usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    }
+    // TODO(user): FrameBuffer is assumed to be RGBA
+    target_width = std::max(target_width, width);
+    target_height += height;
+
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width, height,
+                                 INT(HAL_PIXEL_FORMAT_RGBA_8888), usage, aligned_w, aligned_h);
+
+    target_aligned_width = std::max(target_aligned_width, aligned_w);
+    target_aligned_height += aligned_h;
+
+    // Left will be zero always
+    dst_rects[processed_blit].top = FLOAT(target_aligned_height - aligned_h);
+    dst_rects[processed_blit].right = dst_rects[processed_blit].left +
+                                      (layer->dst_rect.right - layer->dst_rect.left);
+    dst_rects[processed_blit].bottom = (dst_rects[processed_blit].top +
+                                      (layer->dst_rect.bottom - layer->dst_rect.top));
+    blit_src_rect = dst_rects[processed_blit];
+    processed_blit++;
+  }
+
+  // Allocate a single buffer of RGBA8888 format
+  if (blit_needed && (AllocateBlitTargetBuffers(target_width, target_height,
+                                                HAL_PIXEL_FORMAT_RGBA_8888, usage) < 0)) {
+      status = -1;
+      return status;
+  }
+
+  if (blit_needed) {
+    for (uint32_t j = 0; j < num_blit_target_; j++) {
+      Layer *layer = layer_stack->layers.at(j + content_list->numHwLayers);
+      private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_];
+      // Set the fd information
+        layer->input_buffer.width = target_aligned_width;
+        layer->input_buffer.height = target_aligned_height;
+        layer->input_buffer.unaligned_width = target_width;
+        layer->input_buffer.unaligned_height = target_height;
+      if (target_buffer->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+          layer->input_buffer.format = kFormatRGBA8888Ubwc;
+      }
+      layer->input_buffer.planes[0].fd = target_buffer->fd;
+      layer->input_buffer.planes[0].offset = 0;
+      layer->input_buffer.planes[0].stride = target_buffer->width;
+    }
+  }
+
+  return status;
+}
+
+int BlitEngineC2d::Commit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) {
+  int fd = -1;
+  int status = 0;
+  bool hybrid_present = false;
+  uint32_t num_app_layers = (uint32_t) content_list->numHwLayers-1;
+  private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_];
+  blit_active_ = false;
+
+  if (!num_app_layers) {
+    return -1;
+  }
+
+  // if not Blit Targets return
+  for (uint32_t i = 0; i < num_app_layers; i++) {
+    Layer *layer = layer_stack->layers.at(i);
+    if (layer->composition == kCompositionHybrid || layer->composition == kCompositionBlit) {
+      hybrid_present = true;
+    }
+  }
+
+  if (!hybrid_present) {
+    return status;
+  }
+
+  // Clear blit target buffer
+  LayerRect clear_rect;
+  clear_rect.left =  0;
+  clear_rect.top = 0;
+  clear_rect.right = FLOAT(target_buffer->width);
+  clear_rect.bottom = FLOAT(target_buffer->height);
+  ClearTargetBuffer(target_buffer, clear_rect);
+
+  int copybit_layer_count = 0;
+  uint32_t processed_blit = 0;
+  for (uint32_t i = num_app_layers-1; (i > 0) && (processed_blit < num_blit_target_) &&
+      (status == 0); i--) {
+    Layer *layer = layer_stack->layers.at(i);
+    if (layer->composition != kCompositionBlit) {
+      continue;
+    }
+
+    for (uint32_t k = 0; k <= i; k++) {
+      Layer *bottom_layer = layer_stack->layers.at(k);
+      LayerBuffer &layer_buffer = bottom_layer->input_buffer;
+      // if layer below the blit layer does not intersect, ignore that layer
+      LayerRect inter_sect = Intersection(layer->dst_rect, bottom_layer->dst_rect);
+      if (bottom_layer->composition != kCompositionHybrid && !IsValid(inter_sect)) {
+        continue;
+      }
+      if (bottom_layer->composition == kCompositionGPU ||
+          bottom_layer->composition == kCompositionSDE ||
+          bottom_layer->composition == kCompositionGPUTarget) {
+        continue;
+      }
+
+      // For each layer marked as Hybrid, wait for acquire fence and then blit using the C2D
+      if (layer_buffer.acquire_fence_fd >= 0) {
+        // Wait for acquire fence on the App buffers.
+        if (sync_wait(layer_buffer.acquire_fence_fd, 1000) < 0) {
+          DLOGE("sync_wait error!! error no = %d err str = %s", errno, strerror(errno));
+        }
+        layer_buffer.acquire_fence_fd = -1;
+      }
+      hwc_layer_1_t *hwc_layer = &content_list->hwLayers[k];
+      LayerRect &src_rect = bottom_layer->blit_regions.at(processed_blit);
+      Layer *blit_layer = layer_stack->layers.at(blit_target_start_index_ + processed_blit);
+      LayerRect dest_rect = blit_layer->src_rect;
+      int ret_val = DrawRectUsingCopybit(hwc_layer, bottom_layer, src_rect, dest_rect);
+      copybit_layer_count++;
+      if (ret_val < 0) {
+        copybit_layer_count = 0;
+        DLOGE("DrawRectUsingCopyBit failed");
+        status = -1;
+        break;
+      }
+    }
+    processed_blit++;
+  }
+
+  if (copybit_layer_count) {
+    blit_active_ = true;
+    blit_engine_c2d_->flush_get_fence(blit_engine_c2d_, &fd);
+  }
+
+  if (blit_active_) {
+    // dump the render buffer
+    DumpBlitTargetBuffer(fd);
+
+    // Set the fd to the LayerStack BlitTargets fd
+    uint32_t layer_count = UINT32(layer_stack->layers.size());
+    for (uint32_t k = blit_target_start_index_; k < layer_count; k++) {
+      Layer *layer = layer_stack->layers.at(k);
+      LayerBuffer &layer_buffer = layer->input_buffer;
+      layer_buffer.acquire_fence_fd = fd;
+    }
+  }
+
+  return status;
+}
+
+int BlitEngineC2d::DrawRectUsingCopybit(hwc_layer_1_t *hwc_layer, Layer *layer,
+                                        LayerRect blit_rect, LayerRect blit_dest_Rect) {
+  private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_];
+  const private_handle_t *hnd = static_cast<const private_handle_t *>(hwc_layer->handle);
+  LayerBuffer &layer_buffer = layer->input_buffer;
+
+  // Set the Copybit Source
+  copybit_image_t src;
+  src.handle = const_cast<native_handle_t *>(hwc_layer->handle);
+  src.w = hnd->width;
+  src.h = hnd->height;
+  src.base = reinterpret_cast<void *>(hnd->base);
+  src.format = hnd->format;
+  src.horiz_padding = 0;
+  src.vert_padding = 0;
+
+  // Copybit source rect
+  copybit_rect_t src_rect = {INT(blit_rect.left), INT(blit_rect.top), INT(blit_rect.right),
+                            INT(blit_rect.bottom)};
+
+  // Copybit destination rect
+  copybit_rect_t dst_rect = {INT(blit_dest_Rect.left), INT(blit_dest_Rect.top),
+                            INT(blit_dest_Rect.right), INT(blit_dest_Rect.bottom)};
+
+  // Copybit destination buffer
+  copybit_image_t dst;
+  dst.handle = static_cast<native_handle_t *>(target_buffer);
+  dst.w = ALIGN(target_buffer->width, 32);
+  dst.h = ALIGN((target_buffer->height), 32);
+  dst.base = reinterpret_cast<void *>(target_buffer->base);
+  dst.format = target_buffer->format;
+
+  // Copybit region is the destRect
+  LayerRect region_rect;
+  region_rect.left = FLOAT(dst_rect.l);
+  region_rect.top = FLOAT(dst_rect.t);
+  region_rect.right = FLOAT(dst_rect.r);
+  region_rect.bottom = FLOAT(dst_rect.b);
+
+  LayerRectArray region;
+  region.count = 1;
+  region.rect  = &region_rect;
+  RegionIterator copybitRegion(region);
+  int acquireFd = layer_buffer.acquire_fence_fd;
+
+  // FRAMEBUFFER_WIDTH/HEIGHT for c2d is the target buffer w/h
+  blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_FRAMEBUFFER_WIDTH,
+                                  target_buffer->width);
+  blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_FRAMEBUFFER_HEIGHT,
+                                  target_buffer->height);
+  int transform = 0;
+  if (layer->transform.rotation != 0.0f) transform |= COPYBIT_TRANSFORM_ROT_90;
+  if (layer->transform.flip_horizontal) transform |= COPYBIT_TRANSFORM_FLIP_H;
+  if (layer->transform.flip_vertical) transform |= COPYBIT_TRANSFORM_FLIP_V;
+  blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_TRANSFORM, transform);
+  blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_PLANE_ALPHA, hwc_layer->planeAlpha);
+  blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_BLEND_MODE, hwc_layer->blending);
+  blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_DITHER,
+    (dst.format == HAL_PIXEL_FORMAT_RGB_565) ? COPYBIT_ENABLE : COPYBIT_DISABLE);
+
+  int src_format_mode = COPYBIT_LINEAR;
+  if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+    src_format_mode = COPYBIT_UBWC_COMPRESSED;
+  }
+  blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_SRC_FORMAT_MODE, src_format_mode);
+
+  blit_engine_c2d_->set_sync(blit_engine_c2d_, acquireFd);
+  int err = blit_engine_c2d_->stretch(blit_engine_c2d_, &dst, &src, &dst_rect, &src_rect,
+                                      &copybitRegion);
+
+  if (err < 0) {
+    DLOGE("copybit stretch failed");
+  }
+
+  return err;
+}
+
+void BlitEngineC2d::DumpBlitTargetBuffer(int fd) {
+  if (!dump_frame_count_) {
+    return;
+  }
+
+  private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_];
+
+  if (fd >= 0) {
+    int error = sync_wait(fd, 1000);
+    if (error < 0) {
+      DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+      return;
+    }
+  }
+
+  char dump_file_name[PATH_MAX];
+  size_t result = 0;
+  snprintf(dump_file_name, sizeof(dump_file_name), "/data/misc/display/frame_dump_primary"
+           "/blit_target_%d.raw", (dump_frame_index_));
+  FILE* fp = fopen(dump_file_name, "w+");
+  if (fp) {
+    result = fwrite(reinterpret_cast<void *>(target_buffer->base), target_buffer->size, 1, fp);
+    fclose(fp);
+  }
+  dump_frame_count_--;
+  dump_frame_index_++;
+}
+
+}  // namespace sdm
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
diff --git a/sdm845/sdm/libs/hwc/blit_engine_c2d.h b/sdm845/sdm/libs/hwc/blit_engine_c2d.h
new file mode 100644
index 0000000..6536d44
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/blit_engine_c2d.h
@@ -0,0 +1,121 @@
+/* Copyright (c) 2012 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*  * Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above
+*    copyright notice, this list of conditions and the following
+*    disclaimer in the documentation and/or other materials provided
+*    with the distribution.
+*  * Neither the name of The Linux Foundation nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+* Portions formerly licensed under Apache License, Version 2.0, are re licensed
+* under section 4 of Apache License, Version 2.0.
+
+* Copyright (C) 2010 The Android Open Source Project
+
+* Not a Contribution.
+
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+
+* http://www.apache.org/licenses/LICENSE-2.0
+
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/*! @file blit_engine.h
+  @brief Interface file for Blit based compositior.
+
+  @details The client can use this interface to get the blit composition done
+
+*/
+
+#include <hardware/hwcomposer.h>
+#include <core/layer_stack.h>
+#include <copybit.h>
+#include "blit_engine.h"
+
+#ifndef __BLIT_ENGINE_C2D_H__
+#define __BLIT_ENGINE_C2D_H__
+
+namespace sdm {
+
+// C2D Blit implemented by the client
+// This class implements the BlitEngine Interface which is used to get the
+// Blit composition using C2D
+class BlitEngineC2d : public BlitEngine {
+ public:
+  BlitEngineC2d();
+  virtual ~BlitEngineC2d();
+
+  virtual int Init();
+  virtual void DeInit();
+  virtual int Prepare(LayerStack *layer_stack);
+  virtual int PreCommit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack);
+  virtual int Commit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack);
+  virtual void PostCommit(LayerStack *layer_stack);
+  virtual bool BlitActive();
+  virtual void SetFrameDumpConfig(uint32_t count);
+
+
+ private:
+  static const uint32_t kNumBlitTargetBuffers = 3;
+
+  struct Range {
+    int current;
+    int end;
+  };
+
+  struct RegionIterator : public copybit_region_t {
+    explicit RegionIterator(LayerRectArray rect);
+   private:
+    static int iterate(copybit_region_t const *self, copybit_rect_t *rect);
+    LayerRectArray rect_array;
+    mutable Range r;
+  };
+
+  int AllocateBlitTargetBuffers(uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
+  void FreeBlitTargetBuffers();
+  int ClearTargetBuffer(private_handle_t* hnd, const LayerRect& rect);
+  int DrawRectUsingCopybit(hwc_layer_1_t *hwc_layer, Layer *layer, LayerRect blit_rect,
+                           LayerRect blit_dest_Rect);
+  void SetReleaseFence(int fence_fd);
+  void DumpBlitTargetBuffer(int fd);
+
+  copybit_device_t *blit_engine_c2d_ = NULL;
+  private_handle_t *blit_target_buffer_[kNumBlitTargetBuffers];
+  uint32_t current_blit_target_index_ = 0;
+  int release_fence_fd_[kNumBlitTargetBuffers];
+  uint32_t num_blit_target_ = 0;
+  int blit_target_start_index_ = 0;
+  bool blit_active_ = false;
+  uint32_t dump_frame_count_ = 0;
+  uint32_t dump_frame_index_ = 0;
+};
+
+}  // namespace sdm
+
+#endif  // __BLIT_ENGINE_C2D_H__
diff --git a/sdm845/sdm/libs/hwc/cpuhint.cpp b/sdm845/sdm/libs/hwc/cpuhint.cpp
new file mode 100644
index 0000000..551fa24
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/cpuhint.cpp
@@ -0,0 +1,108 @@
+/* Copyright (c) 2015, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* 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 <dlfcn.h>
+#include <utils/debug.h>
+
+#include "cpuhint.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "CPUHint"
+
+namespace sdm {
+
+DisplayError CPUHint::Init(HWCDebugHandler *debug_handler) {
+  char path[PROPERTY_VALUE_MAX];
+  if (debug_handler->GetProperty("ro.vendor.extension_library", path) != kErrorNone) {
+    DLOGI("Vendor Extension Library not enabled");
+    return kErrorNotSupported;
+  }
+
+  int pre_enable_window = -1;
+  debug_handler->GetProperty("sdm.perf_hint_window", &pre_enable_window);
+  if (pre_enable_window <= 0) {
+    DLOGI("Invalid CPU Hint Pre-enable Window %d", pre_enable_window);
+    return kErrorNotSupported;
+  }
+
+  DLOGI("CPU Hint Pre-enable Window %d", pre_enable_window);
+  pre_enable_window_ = pre_enable_window;
+
+  if (vendor_ext_lib_.Open(path)) {
+    if (!vendor_ext_lib_.Sym("perf_lock_acq", reinterpret_cast<void **>(&fn_lock_acquire_)) ||
+        !vendor_ext_lib_.Sym("perf_lock_rel", reinterpret_cast<void **>(&fn_lock_release_))) {
+      DLOGW("Failed to load symbols for Vendor Extension Library");
+      return kErrorNotSupported;
+    }
+    DLOGI("Successfully Loaded Vendor Extension Library symbols");
+    enabled_ = true;
+  } else {
+    DLOGW("Failed to open %s : %s", path, vendor_ext_lib_.Error());
+  }
+
+  return kErrorNone;
+}
+
+void CPUHint::Set() {
+  if (!enabled_) {
+    return;
+  }
+  if (lock_acquired_) {
+    return;
+  }
+  if (frame_countdown_) {
+    --frame_countdown_;
+    return;
+  }
+
+  int hint = HINT;
+  lock_handle_ = fn_lock_acquire_(0 /*handle*/, 0/*duration*/,
+                                  &hint, sizeof(hint) / sizeof(int));
+  if (lock_handle_ >= 0) {
+    lock_acquired_ = true;
+  }
+}
+
+void CPUHint::Reset() {
+  if (!enabled_) {
+    return;
+  }
+
+  frame_countdown_ = pre_enable_window_;
+
+  if (!lock_acquired_) {
+    return;
+  }
+
+  fn_lock_release_(lock_handle_);
+  lock_acquired_ = false;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc/cpuhint.h b/sdm845/sdm/libs/hwc/cpuhint.h
new file mode 100644
index 0000000..e758763
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/cpuhint.h
@@ -0,0 +1,61 @@
+/* Copyright (c) 2015, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* 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 __CPUHINT_H__
+#define __CPUHINT_H__
+
+#include <core/sdm_types.h>
+#include <utils/sys.h>
+
+namespace sdm {
+
+class HWCDebugHandler;
+
+class CPUHint {
+ public:
+  DisplayError Init(HWCDebugHandler *debug_handler);
+  void Set();
+  void Reset();
+
+ private:
+  enum { HINT =  0x4501 /* 45-display layer hint, 01-Enable */ };
+  bool enabled_ = false;
+  // frames to wait before setting this hint
+  int pre_enable_window_ = 0;
+  int frame_countdown_ = 0;
+  int lock_handle_ = 0;
+  bool lock_acquired_ = false;
+  DynLib vendor_ext_lib_;
+  int (*fn_lock_acquire_)(int handle, int duration, int *hints, int num_args) = NULL;
+  int (*fn_lock_release_)(int value) = NULL;
+};
+
+}  // namespace sdm
+
+#endif  // __CPUHINT_H__
diff --git a/sdm845/sdm/libs/hwc/hwc_buffer_allocator.cpp b/sdm845/sdm/libs/hwc/hwc_buffer_allocator.cpp
new file mode 100644
index 0000000..25f366f
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_buffer_allocator.cpp
@@ -0,0 +1,330 @@
+/*
+* Copyright (c) 2015 - 2017, 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 <utils/debug.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 = INT(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_camera) {
+    alloc_flags = GRALLOC_USAGE_HW_CAMERA_WRITE;
+    alloc_flags |= (GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_HW_COMPOSER);
+    data.align = SZ_2M;
+  } else if (buffer_config.secure) {
+    alloc_flags = INT(GRALLOC_USAGE_PRIVATE_MM_HEAP);
+    alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
+    data.align = SECURE_ALIGN;
+  } else {
+    data.align = UINT32(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) {
+    delete meta_buffer_info;
+    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);
+    delete meta_buffer_info;
+    return kErrorMemory;
+  }
+
+  alloc_buffer_info->fd = data.fd;
+  // TODO(user): define stride for all planes and fix stride in bytes
+  alloc_buffer_info->stride = UINT32(aligned_width);
+  alloc_buffer_info->aligned_width = UINT32(aligned_width);
+  alloc_buffer_info->aligned_height = UINT32(aligned_height);
+  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;
+
+  // Deallocate the buffer, only if the buffer fd is valid.
+  if (alloc_buffer_info->fd > 0) {
+    MetaBufferInfo *meta_buffer_info = static_cast<MetaBufferInfo *> (buffer_info->private_data);
+    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->aligned_width = 0;
+    alloc_buffer_info->aligned_height = 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;
+}
+
+uint32_t HWCBufferAllocator::GetBufferSize(BufferInfo *buffer_info) {
+  uint32_t align = UINT32(getpagesize());
+
+  const BufferConfig &buffer_config = buffer_info->buffer_config;
+
+  int alloc_flags = INT(GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
+
+  int width = INT(buffer_config.width);
+  int height = INT(buffer_config.height);
+  int format;
+
+  if (buffer_config.secure_camera) {
+    alloc_flags = GRALLOC_USAGE_HW_CAMERA_WRITE;
+    alloc_flags |= (GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_HW_COMPOSER);
+    align = SZ_2M;
+  } else if (buffer_config.secure) {
+    alloc_flags = INT(GRALLOC_USAGE_PRIVATE_MM_HEAP);
+    alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
+    align = SECURE_ALIGN;
+  }
+
+  if (buffer_config.cache == false) {
+    // Allocate uncached buffers
+    alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+  }
+
+  if (SetBufferInfo(buffer_config.format, &format, &alloc_flags) < 0) {
+    return 0;
+  }
+
+  int aligned_width = 0;
+  int aligned_height = 0;
+  uint32_t buffer_size = getBufferSizeAndDimensions(width, height, format, alloc_flags,
+                                                    aligned_width, aligned_height);
+
+  buffer_size = ROUND_UP(buffer_size, align) * buffer_config.buffer_count;
+
+  return buffer_size;
+}
+
+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 kFormatBGR565:                   *target = HAL_PIXEL_FORMAT_BGR_565;               break;
+  case kFormatBGRA8888:                 *target = HAL_PIXEL_FORMAT_BGRA_8888;             break;
+  case kFormatYCrCb420PlanarStride16:   *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 kFormatCbYCrY422H2V1Packed:      *target = HAL_PIXEL_FORMAT_CbYCrY_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 kFormatYCrCb420SemiPlanarVenus:  *target = HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS;    break;
+  case kFormatYCbCr420SPVenusUbwc:
+    *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+    *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    break;
+  case kFormatRGBA5551:                 *target = HAL_PIXEL_FORMAT_RGBA_5551;             break;
+  case kFormatRGBA4444:                 *target = HAL_PIXEL_FORMAT_RGBA_4444;             break;
+  case kFormatRGBA1010102:              *target = HAL_PIXEL_FORMAT_RGBA_1010102;          break;
+  case kFormatARGB2101010:              *target = HAL_PIXEL_FORMAT_ARGB_2101010;          break;
+  case kFormatRGBX1010102:              *target = HAL_PIXEL_FORMAT_RGBX_1010102;          break;
+  case kFormatXRGB2101010:              *target = HAL_PIXEL_FORMAT_XRGB_2101010;          break;
+  case kFormatBGRA1010102:              *target = HAL_PIXEL_FORMAT_BGRA_1010102;          break;
+  case kFormatABGR2101010:              *target = HAL_PIXEL_FORMAT_ABGR_2101010;          break;
+  case kFormatBGRX1010102:              *target = HAL_PIXEL_FORMAT_BGRX_1010102;          break;
+  case kFormatXBGR2101010:              *target = HAL_PIXEL_FORMAT_XBGR_2101010;          break;
+  case kFormatYCbCr420P010:             *target = HAL_PIXEL_FORMAT_YCbCr_420_P010;        break;
+  case kFormatYCbCr420TP10Ubwc:
+    *target = HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC;
+    *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    break;
+  case kFormatYCbCr420P010Ubwc:
+    *target = HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC;
+    *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    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 kFormatBGR565Ubwc:
+    *target = HAL_PIXEL_FORMAT_BGR_565;
+    *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    break;
+  case kFormatRGBA1010102Ubwc:
+    *target = HAL_PIXEL_FORMAT_RGBA_1010102;
+    *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    break;
+  case kFormatRGBX1010102Ubwc:
+    *target = HAL_PIXEL_FORMAT_RGBX_1010102;
+    *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    break;
+  default:
+    DLOGE("Unsupported format = 0x%x", format);
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
+DisplayError HWCBufferAllocator::GetAllocatedBufferInfo(const BufferConfig &buffer_config,
+                                 AllocatedBufferInfo *allocated_buffer_info) {
+  int width = INT(buffer_config.width);
+  int height = INT(buffer_config.height);
+  int alloc_flags = INT(GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
+
+  if (buffer_config.secure) {
+    alloc_flags = INT(GRALLOC_USAGE_PRIVATE_MM_HEAP);
+    alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
+  }
+
+  if (buffer_config.cache == false) {
+    // Allocate uncached buffers
+    alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+  }
+
+  int format;
+  int error = SetBufferInfo(buffer_config.format, &format, &alloc_flags);
+  if (error) {
+    DLOGE("Failed: format = %d or width = %d height = %d", buffer_config.format, width, height);
+    return kErrorNotSupported;
+  }
+
+  int width_aligned = 0, height_aligned = 0;
+  uint32_t buffer_size = 0;
+  buffer_size = getBufferSizeAndDimensions(width, height, format, alloc_flags,
+                                           width_aligned, height_aligned);
+
+  allocated_buffer_info->stride = UINT32(width_aligned);
+  allocated_buffer_info->aligned_width = UINT32(width_aligned);
+  allocated_buffer_info->aligned_height = UINT32(height_aligned);
+  allocated_buffer_info->size = UINT32(buffer_size);
+  allocated_buffer_info->format = buffer_config.format;
+
+  return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::GetBufferLayout(const AllocatedBufferInfo &buf_info,
+                                                 uint32_t stride[4], uint32_t offset[4],
+                                                 uint32_t *num_planes) {
+  private_handle_t hnd(-1, 0, 0, 0, 0, 0, 0);
+  int format = HAL_PIXEL_FORMAT_RGBA_8888;
+  int flags = 0;
+
+  SetBufferInfo(buf_info.format, &format, &flags);
+  // Setup only the required stuff, skip rest
+  hnd.format = format;
+  hnd.width = buf_info.aligned_width;
+  hnd.height = buf_info.aligned_height;
+  if (flags & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) {
+    hnd.flags = private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+  }
+
+  int ret = getBufferLayout(&hnd, stride, offset, num_planes);
+  if (ret < 0) {
+    DLOGE("getBufferLayout failed");
+    return kErrorParameters;
+  }
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc/hwc_buffer_allocator.h b/sdm845/sdm/libs/hwc/hwc_buffer_allocator.h
new file mode 100644
index 0000000..a8cf462
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_buffer_allocator.h
@@ -0,0 +1,70 @@
+/*
+* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*  * Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above
+*    copyright notice, this list of conditions and the following
+*    disclaimer in the documentation and/or other materials provided
+*    with the distribution.
+*  * Neither the name of The Linux Foundation nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef __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);
+  uint32_t GetBufferSize(BufferInfo *buffer_info);
+  DisplayError GetAllocatedBufferInfo(const BufferConfig &buffer_config,
+                                      AllocatedBufferInfo *allocated_buffer_info);
+  DisplayError GetBufferLayout(const AllocatedBufferInfo &buf_info,
+                               uint32_t stride[4], uint32_t offset[4],
+                               uint32_t *num_planes);
+  int SetBufferInfo(LayerBufferFormat format, int *target, int *flags);
+
+ 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.
+  };
+
+  gralloc::IAllocController *alloc_controller_;
+};
+
+}  // namespace sdm
+#endif  // __HWC_BUFFER_ALLOCATOR_H__
+
diff --git a/sdm845/sdm/libs/hwc/hwc_buffer_sync_handler.cpp b/sdm845/sdm/libs/hwc/hwc_buffer_sync_handler.cpp
new file mode 100644
index 0000000..784e91b
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_buffer_sync_handler.cpp
@@ -0,0 +1,91 @@
+/*
+* 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 <utils/debug.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));
+      return kErrorTimeOut;
+    }
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWCBufferSyncHandler::SyncMerge(int fd1, int fd2, int *merged_fd) {
+  DisplayError error = kErrorNone;
+
+  // Merge the two fences.  In the case where one of the fences is not a
+  // valid fence (e.g. NO_FENCE) merge the one valid fence with itself so
+  // that a new fence with the given name is created.
+  // TODO(user): "SyncMerge"string should be replaced with user-defined string to represent
+  // why it is merged.
+  if (fd1 >= 0 && fd2 >= 0) {
+    *merged_fd = sync_merge("SyncMerge", fd1, fd2);
+  } else if (fd1 >= 0) {
+    *merged_fd = sync_merge("SyncMerge", fd1, fd1);
+  } else if (fd2 >= 0) {
+    *merged_fd = sync_merge("SyncMerge", fd2, fd2);
+  } else {
+    *merged_fd = -1;
+    return kErrorNone;
+  }
+
+  if (*merged_fd == -1) {
+    DLOGE("Sync merge error! fd1 %d fd2 %d", fd1, fd2);
+    error = kErrorFileDescriptor;
+  }
+
+  return error;
+}
+
+bool HWCBufferSyncHandler::IsSyncSignaled(int fd) {
+  if (sync_wait(fd, 0) < 0) {
+    return false;
+  } else {
+    return true;
+  }
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/hwc/hwc_buffer_sync_handler.h b/sdm845/sdm/libs/hwc/hwc_buffer_sync_handler.h
new file mode 100644
index 0000000..81479d8
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_buffer_sync_handler.h
@@ -0,0 +1,53 @@
+/*
+* 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);
+  virtual bool IsSyncSignaled(int fd);
+};
+
+}  // namespace sdm
+#endif  // __HWC_BUFFER_SYNC_HANDLER_H__
+
+
diff --git a/sdm845/sdm/libs/hwc/hwc_color_manager.cpp b/sdm845/sdm/libs/hwc/hwc_color_manager.cpp
new file mode 100644
index 0000000..471ca49
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_color_manager.cpp
@@ -0,0 +1,652 @@
+/*
+* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <dlfcn.h>
+#include <powermanager/IPowerManager.h>
+#include <cutils/sockets.h>
+#include <cutils/native_handle.h>
+#include <utils/String16.h>
+#include <binder/Parcel.h>
+#include <gralloc_priv.h>
+#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer_defs.h>
+#include <QService.h>
+
+#include <core/dump_interface.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <core/buffer_allocator.h>
+#include <private/color_params.h>
+#include "hwc_buffer_allocator.h"
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_session.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCColorManager"
+
+namespace sdm {
+
+uint32_t HWCColorManager::Get8BitsARGBColorValue(const PPColorFillParams &params) {
+  uint32_t argb_color = ((params.color.r << 16) & 0xff0000) | ((params.color.g << 8) & 0xff00) |
+                        ((params.color.b) & 0xff);
+  return argb_color;
+}
+
+int HWCColorManager::CreatePayloadFromParcel(const android::Parcel &in, uint32_t *disp_id,
+                                             PPDisplayAPIPayload *sink) {
+  int ret = 0;
+  uint32_t id(0);
+  uint32_t size(0);
+
+  id = UINT32(in.readInt32());
+  size = UINT32(in.readInt32());
+  if (size > 0 && size == in.dataAvail()) {
+    const void *data = in.readInplace(size);
+    const uint8_t *temp = reinterpret_cast<const uint8_t *>(data);
+
+    sink->size = size;
+    sink->payload = const_cast<uint8_t *>(temp);
+    *disp_id = id;
+  } else {
+    DLOGW("Failing size checking, size = %d", size);
+    ret = -EINVAL;
+  }
+
+  return ret;
+}
+
+void HWCColorManager::MarshallStructIntoParcel(const PPDisplayAPIPayload &data,
+                                               android::Parcel *out_parcel) {
+  out_parcel->writeInt32(INT32(data.size));
+  if (data.payload)
+    out_parcel->write(data.payload, data.size);
+}
+
+HWCColorManager *HWCColorManager::CreateColorManager() {
+  HWCColorManager *color_mgr = new HWCColorManager();
+
+  if (color_mgr) {
+    // Load display API interface library. And retrieve color API function tables.
+    DynLib &color_apis_lib = color_mgr->color_apis_lib_;
+    if (color_apis_lib.Open(DISPLAY_API_INTERFACE_LIBRARY_NAME)) {
+      if (!color_apis_lib.Sym(DISPLAY_API_FUNC_TABLES, &color_mgr->color_apis_)) {
+        DLOGE("Fail to retrieve = %s from %s", DISPLAY_API_FUNC_TABLES,
+              DISPLAY_API_INTERFACE_LIBRARY_NAME);
+        delete color_mgr;
+        return NULL;
+      }
+    } else {
+      DLOGW("Unable to load = %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
+      delete color_mgr;
+      return NULL;
+    }
+    DLOGI("Successfully loaded %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
+
+    // Load diagclient library and invokes its entry point to pass in display APIs.
+    DynLib &diag_client_lib = color_mgr->diag_client_lib_;
+    if (diag_client_lib.Open(QDCM_DIAG_CLIENT_LIBRARY_NAME)) {
+      if (!diag_client_lib.Sym(INIT_QDCM_DIAG_CLIENT_NAME,
+                               reinterpret_cast<void **>(&color_mgr->qdcm_diag_init_)) ||
+        !diag_client_lib.Sym(DEINIT_QDCM_DIAG_CLIENT_NAME,
+                               reinterpret_cast<void **>(&color_mgr->qdcm_diag_deinit_))) {
+        DLOGE("Fail to retrieve = %s from %s", INIT_QDCM_DIAG_CLIENT_NAME,
+              QDCM_DIAG_CLIENT_LIBRARY_NAME);
+      } else {
+        // invoke Diag Client entry point to initialize.
+        color_mgr->qdcm_diag_init_(color_mgr->color_apis_);
+        DLOGI("Successfully loaded %s and %s and diag_init'ed", DISPLAY_API_INTERFACE_LIBRARY_NAME,
+              QDCM_DIAG_CLIENT_LIBRARY_NAME);
+      }
+    } else {
+      DLOGW("Unable to load = %s", QDCM_DIAG_CLIENT_LIBRARY_NAME);
+      // only QDCM Diag client failed to be loaded and system still should function.
+    }
+  } else {
+    DLOGE("Unable to create HWCColorManager");
+    return NULL;
+  }
+
+  return color_mgr;
+}
+
+HWCColorManager::~HWCColorManager() {
+}
+
+void HWCColorManager::DestroyColorManager() {
+  if (qdcm_mode_mgr_) {
+    delete qdcm_mode_mgr_;
+  }
+  if (qdcm_diag_deinit_) {
+    qdcm_diag_deinit_();
+  }
+  delete this;
+}
+
+int HWCColorManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
+  int ret = 0;
+
+  if (!qdcm_mode_mgr_) {
+    qdcm_mode_mgr_ = HWCQDCMModeManager::CreateQDCMModeMgr();
+    if (!qdcm_mode_mgr_) {
+      DLOGE("Unable to create QDCM operating mode manager.");
+      ret = -EFAULT;
+    }
+  }
+
+  if (qdcm_mode_mgr_) {
+    ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display);
+  }
+
+  return ret;
+}
+
+bool HWCColorManager::SolidFillLayersPrepare(hwc_display_contents_1_t **displays,
+                                             HWCDisplay *hwc_display) {
+  SCOPE_LOCK(locker_);
+
+  // Query HWCColorManager if QDCM tool requesting SOLID_FILL mode.
+  uint32_t solid_fill_color = Get8BitsARGBColorValue(solid_fill_params_);
+  hwc_display_contents_1_t *layer_list = displays[HWC_DISPLAY_PRIMARY];
+
+  if (solid_fill_enable_ && solid_fill_layers_ && layer_list) {
+    // 1. shallow copy HWC_FRAMEBUFFER_TARGET layer info solid fill layer list.
+    solid_fill_layers_->hwLayers[1] = layer_list->hwLayers[layer_list->numHwLayers - 1];
+
+    // 2. continue the prepare<> on solid_fill_layers.
+    hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_INFO, solid_fill_color);
+    hwc_display->Prepare(solid_fill_layers_);  // RECT info included.
+
+    // 3. Set HWC_OVERLAY to all SF layers before returning to framework.
+    for (size_t i = 0; i < (layer_list->numHwLayers - 1); i++) {
+      hwc_layer_1_t *layer = &layer_list->hwLayers[i];
+      layer->compositionType = HWC_OVERLAY;
+    }
+
+    return true;
+  } else if (!solid_fill_enable_) {
+    hwc_display->Perform(HWCDisplayPrimary::UNSET_QDCM_SOLID_FILL_INFO, 0);
+  }
+
+  return false;
+}
+
+bool HWCColorManager::SolidFillLayersSet(hwc_display_contents_1_t **displays,
+                                         HWCDisplay *hwc_display) {
+  // Query HWCColorManager if QDCM tool requesting SOLID_FILL mode.
+  SCOPE_LOCK(locker_);
+  hwc_display_contents_1_t *layer_list = displays[HWC_DISPLAY_PRIMARY];
+  if (solid_fill_enable_ && solid_fill_layers_ && layer_list) {
+    hwc_display->Commit(solid_fill_layers_);
+
+    // SurfaceFlinger layer stack is dropped in solid fill case and replaced with local layer stack
+    // Close acquire fence fds associated with SF layer stack
+    // Close release/retire fence fds returned along with local layer stack
+    for (size_t i = 0; i < (layer_list->numHwLayers - 1); i++) {
+      int &fence_fd = layer_list->hwLayers[i].acquireFenceFd;
+      if (fence_fd >= 0) {
+        close(fence_fd);
+        fence_fd = -1;
+      }
+    }
+
+    for (size_t i = 0; i < (solid_fill_layers_->numHwLayers - 1); i++) {
+      int &fence_fd = solid_fill_layers_->hwLayers[i].releaseFenceFd;
+      if (fence_fd >= 0) {
+        close(fence_fd);
+        fence_fd = -1;
+      }
+    }
+    if (solid_fill_layers_->retireFenceFd >= 0) {
+      close(solid_fill_layers_->retireFenceFd);
+      solid_fill_layers_->retireFenceFd = -1;
+    }
+
+    return true;
+  }
+
+  return false;
+}
+
+int HWCColorManager::CreateSolidFillLayers(HWCDisplay *hwc_display) {
+  int ret = 0;
+
+  if (!solid_fill_layers_) {
+    uint32_t size = sizeof(hwc_display_contents_1) + kNumSolidFillLayers * sizeof(hwc_layer_1_t);
+    uint32_t primary_width = 0;
+    uint32_t primary_height = 0;
+
+    hwc_display->GetMixerResolution(&primary_width, &primary_height);
+    uint8_t *buf = new uint8_t[size]();
+    // handle for solid fill layer with fd = -1.
+    private_handle_t *handle =
+        new private_handle_t(-1, 0, private_handle_t::PRIV_FLAGS_FRAMEBUFFER, BUFFER_TYPE_UI,
+                             HAL_PIXEL_FORMAT_RGBA_8888, INT32(primary_width),
+                             INT32(primary_height));
+
+    if (!buf || !handle) {
+      DLOGE("Failed to allocate memory.");
+      if (buf)
+        delete[] buf;
+      if (handle)
+        delete handle;
+
+      return -ENOMEM;
+    }
+
+    solid_fill_layers_ = reinterpret_cast<hwc_display_contents_1 *>(buf);
+    hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
+    layer.handle = handle;
+  }
+
+  solid_fill_layers_->flags = HWC_GEOMETRY_CHANGED;
+  solid_fill_layers_->numHwLayers = kNumSolidFillLayers;
+  solid_fill_layers_->retireFenceFd = -1;
+  solid_fill_layers_->outbuf = NULL;
+  solid_fill_layers_->outbufAcquireFenceFd = -1;
+
+  hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
+  hwc_rect_t solid_fill_rect = {
+      INT(solid_fill_params_.rect.x),
+      INT(solid_fill_params_.rect.y),
+      solid_fill_params_.rect.x + INT(solid_fill_params_.rect.width),
+      solid_fill_params_.rect.y + INT(solid_fill_params_.rect.height),
+  };
+
+  layer.compositionType = HWC_FRAMEBUFFER;
+  layer.blending = HWC_BLENDING_PREMULT;
+  layer.sourceCropf.left = solid_fill_params_.rect.x;
+  layer.sourceCropf.top = solid_fill_params_.rect.y;
+  layer.sourceCropf.right = UINT32(solid_fill_params_.rect.x) + solid_fill_params_.rect.width;
+  layer.sourceCropf.bottom = UINT32(solid_fill_params_.rect.y) + solid_fill_params_.rect.height;
+  layer.acquireFenceFd = -1;
+  layer.releaseFenceFd = -1;
+  layer.flags = 0;
+  layer.transform = 0;
+  layer.hints = 0;
+  layer.planeAlpha = 0xff;
+  layer.displayFrame = solid_fill_rect;
+  layer.visibleRegionScreen.numRects = 1;
+  layer.visibleRegionScreen.rects = &layer.displayFrame;
+  layer.surfaceDamage.numRects = 0;
+
+  return ret;
+}
+
+void HWCColorManager::DestroySolidFillLayers() {
+  if (solid_fill_layers_) {
+    hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
+    uint8_t *buf = reinterpret_cast<uint8_t *>(solid_fill_layers_);
+    private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(layer.handle);
+
+    if (hnd)
+        delete hnd;
+
+    if (buf)
+        delete[] buf;
+
+    solid_fill_layers_ = NULL;
+  }
+}
+
+int HWCColorManager::SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display) {
+  SCOPE_LOCK(locker_);
+  int ret = 0;
+
+  if (params) {
+    solid_fill_params_ = *reinterpret_cast<const PPColorFillParams *>(params);
+  } else {
+    solid_fill_params_ = PPColorFillParams();
+  }
+
+  if (enable) {
+    // will create solid fill layers for rendering if not present.
+    ret = CreateSolidFillLayers(hwc_display);
+  } else {
+    DestroySolidFillLayers();
+  }
+  solid_fill_enable_ = enable;
+
+  return ret;
+}
+
+int HWCColorManager::SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display) {
+  SCOPE_LOCK(locker_);
+  int ret = 0;
+
+  PPFrameCaptureData *frame_capture_data = reinterpret_cast<PPFrameCaptureData*>(params);
+
+  if (enable) {
+    std::memset(&buffer_info, 0x00, sizeof(buffer_info));
+    hwc_display->GetPanelResolution(&buffer_info.buffer_config.width,
+                                    &buffer_info.buffer_config.height);
+    if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_888) {
+      buffer_info.buffer_config.format = kFormatRGB888;
+    } else if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_2101010) {
+      buffer_info.buffer_config.format = kFormatRGBA1010102;
+    } else {
+      DLOGE("Pixel-format: %d NOT support.", frame_capture_data->input_params.out_pix_format);
+      return -EFAULT;
+    }
+
+    buffer_info.buffer_config.buffer_count = 1;
+    buffer_info.alloc_buffer_info.fd = -1;
+    buffer_info.alloc_buffer_info.stride = 0;
+    buffer_info.alloc_buffer_info.size = 0;
+
+    buffer_allocator_ = new HWCBufferAllocator();
+    if (buffer_allocator_ == NULL) {
+      DLOGE("Memory allocation for buffer_allocator_ FAILED");
+      return -ENOMEM;
+    }
+
+    ret = buffer_allocator_->AllocateBuffer(&buffer_info);
+    if (ret != 0) {
+      DLOGE("Buffer allocation failed. ret: %d", ret);
+      delete buffer_allocator_;
+      buffer_allocator_ = NULL;
+      return -ENOMEM;
+    } else {
+      void *buffer = mmap(NULL, buffer_info.alloc_buffer_info.size,
+                          PROT_READ|PROT_WRITE,
+                          MAP_SHARED, buffer_info.alloc_buffer_info.fd, 0);
+
+      if (buffer == MAP_FAILED) {
+        DLOGE("mmap failed. err = %d", errno);
+        frame_capture_data->buffer = NULL;
+        ret = buffer_allocator_->FreeBuffer(&buffer_info);
+        delete buffer_allocator_;
+        buffer_allocator_ = NULL;
+        return -EFAULT;
+      } else {
+        frame_capture_data->buffer = reinterpret_cast<uint8_t *>(buffer);
+        frame_capture_data->buffer_stride = buffer_info.alloc_buffer_info.aligned_width;
+        frame_capture_data->buffer_size = buffer_info.alloc_buffer_info.size;
+      }
+      ret = hwc_display->FrameCaptureAsync(buffer_info, 1);
+      if (ret < 0) {
+        DLOGE("FrameCaptureAsync failed. ret = %d", ret);
+      }
+    }
+  } else {
+    ret = hwc_display->GetFrameCaptureStatus();
+    if (!ret) {
+      if (frame_capture_data->buffer != NULL) {
+        if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) {
+          DLOGE("munmap failed. err = %d", errno);
+        }
+      }
+      if (buffer_allocator_ != NULL) {
+        std::memset(frame_capture_data, 0x00, sizeof(PPFrameCaptureData));
+        ret = buffer_allocator_->FreeBuffer(&buffer_info);
+        if (ret != 0) {
+          DLOGE("FreeBuffer failed. ret = %d", ret);
+        }
+        delete buffer_allocator_;
+        buffer_allocator_ = NULL;
+      }
+    } else {
+      DLOGE("GetFrameCaptureStatus failed. ret = %d", ret);
+    }
+  }
+  return ret;
+}
+
+int HWCColorManager::SetHWDetailedEnhancerConfig(void *params, HWCDisplay *hwc_display) {
+  int err = -1;
+  DisplayDetailEnhancerData de_data;
+
+  PPDETuningCfgData *de_tuning_cfg_data = reinterpret_cast<PPDETuningCfgData*>(params);
+  if (de_tuning_cfg_data->cfg_pending == true) {
+    if (!de_tuning_cfg_data->cfg_en) {
+      de_data.override_flags = kOverrideDEEnable;
+      de_data.enable = 0;
+    } else {
+      de_data.override_flags = kOverrideDEEnable;
+      de_data.enable = 1;
+
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagSharpFactor) {
+        de_data.override_flags |= kOverrideDESharpen1;
+        de_data.sharp_factor = de_tuning_cfg_data->params.sharp_factor;
+      }
+
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagClip) {
+        de_data.override_flags |= kOverrideDEClip;
+        de_data.clip = de_tuning_cfg_data->params.clip;
+      }
+
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrQuiet) {
+        de_data.override_flags |= kOverrideDEThrQuiet;
+        de_data.thr_quiet = de_tuning_cfg_data->params.thr_quiet;
+      }
+
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrDieout) {
+        de_data.override_flags |= kOverrideDEThrDieout;
+        de_data.thr_dieout = de_tuning_cfg_data->params.thr_dieout;
+      }
+
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrLow) {
+        de_data.override_flags |= kOverrideDEThrLow;
+        de_data.thr_low = de_tuning_cfg_data->params.thr_low;
+      }
+
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrHigh) {
+        de_data.override_flags |= kOverrideDEThrHigh;
+        de_data.thr_high = de_tuning_cfg_data->params.thr_high;
+      }
+
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagContentQualLevel) {
+        switch (de_tuning_cfg_data->params.quality) {
+          case kDeContentQualLow:
+            de_data.quality_level = kContentQualityLow;
+            break;
+          case kDeContentQualMedium:
+            de_data.quality_level = kContentQualityMedium;
+            break;
+          case kDeContentQualHigh:
+            de_data.quality_level = kContentQualityHigh;
+            break;
+          case kDeContentQualUnknown:
+          default:
+            de_data.quality_level = kContentQualityUnknown;
+            break;
+        }
+      }
+    }
+    err = hwc_display->SetDetailEnhancerConfig(de_data);
+    if (err) {
+      DLOGW("SetDetailEnhancerConfig failed. err = %d", err);
+    }
+    de_tuning_cfg_data->cfg_pending = false;
+  }
+  return err;
+}
+
+void HWCColorManager::SetColorModeDetailEnhancer(HWCDisplay *hwc_display) {
+  SCOPE_LOCK(locker_);
+  int err = -1;
+  PPPendingParams pending_action;
+  PPDisplayAPIPayload req_payload;
+
+  pending_action.action = kGetDetailedEnhancerData;
+  pending_action.params = NULL;
+
+  if (hwc_display) {
+    err = hwc_display->ColorSVCRequestRoute(req_payload, NULL, &pending_action);
+    if (!err && pending_action.action == kConfigureDetailedEnhancer) {
+      err = SetHWDetailedEnhancerConfig(pending_action.params, hwc_display);
+    }
+  }
+  return;
+}
+
+int HWCColorManager::SetDetailedEnhancer(void *params, HWCDisplay *hwc_display) {
+  SCOPE_LOCK(locker_);
+  int err = -1;
+  err = SetHWDetailedEnhancerConfig(params, hwc_display);
+  return err;
+}
+
+const HWCQDCMModeManager::ActiveFeatureCMD HWCQDCMModeManager::kActiveFeatureCMD[] = {
+    HWCQDCMModeManager::ActiveFeatureCMD("cabl:on", "cabl:off", "cabl:status", "running"),
+    HWCQDCMModeManager::ActiveFeatureCMD("ad:on", "ad:off", "ad:query:status", "running"),
+    HWCQDCMModeManager::ActiveFeatureCMD("svi:on", "svi:off", "svi:status", "running"),
+};
+
+const char *const HWCQDCMModeManager::kSocketName = "pps";
+const char *const HWCQDCMModeManager::kTagName = "surfaceflinger";
+const char *const HWCQDCMModeManager::kPackageName = "colormanager";
+
+HWCQDCMModeManager *HWCQDCMModeManager::CreateQDCMModeMgr() {
+  HWCQDCMModeManager *mode_mgr = new HWCQDCMModeManager();
+
+  if (!mode_mgr) {
+    DLOGW("No memory to create HWCQDCMModeManager.");
+    return NULL;
+  } else {
+    mode_mgr->socket_fd_ =
+        ::socket_local_client(kSocketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+    if (mode_mgr->socket_fd_ < 0) {
+      // it should not be disastrous and we still can grab wakelock in QDCM mode.
+      DLOGW("Unable to connect to dpps socket!");
+    }
+
+    // retrieve system GPU idle timeout value for later to recover.
+    mode_mgr->entry_timeout_ = UINT32(HWCDebugHandler::GetIdleTimeoutMs());
+
+    // acquire the binder handle to Android system PowerManager for later use.
+    android::sp<android::IBinder> binder =
+        android::defaultServiceManager()->checkService(android::String16("power"));
+    if (binder == NULL) {
+      DLOGW("Application can't connect to  power manager service");
+      delete mode_mgr;
+      mode_mgr = NULL;
+    } else {
+      mode_mgr->power_mgr_ = android::interface_cast<android::IPowerManager>(binder);
+    }
+  }
+
+  return mode_mgr;
+}
+
+HWCQDCMModeManager::~HWCQDCMModeManager() {
+  if (socket_fd_ >= 0)
+    ::close(socket_fd_);
+}
+
+int HWCQDCMModeManager::AcquireAndroidWakeLock(bool enable) {
+  int ret = 0;
+
+  if (enable) {
+    if (wakelock_token_ == NULL) {
+      android::sp<android::IBinder> binder = new android::BBinder();
+      android::status_t status = power_mgr_->acquireWakeLock(
+          (kFullWakeLock | kAcquireCauseWakeup | kONAfterRelease), binder,
+          android::String16(kTagName), android::String16(kPackageName));
+      if (status == android::NO_ERROR) {
+        wakelock_token_ = binder;
+      }
+    }
+  } else {
+    if (wakelock_token_ != NULL && power_mgr_ != NULL) {
+      power_mgr_->releaseWakeLock(wakelock_token_, 0);
+      wakelock_token_.clear();
+      wakelock_token_ = NULL;
+    }
+  }
+
+  return ret;
+}
+
+int HWCQDCMModeManager::EnableActiveFeatures(bool enable,
+                                             const HWCQDCMModeManager::ActiveFeatureCMD &cmds,
+                                             bool *was_running) {
+  int ret = 0;
+  ssize_t size = 0;
+  char response[kSocketCMDMaxLength] = {
+      0,
+  };
+
+  if (socket_fd_ < 0) {
+    DLOGW("No socket connection available!");
+    return -EFAULT;
+  }
+
+  if (!enable) {  // if client requesting to disable it.
+    // query CABL status, if off, no action. keep the status.
+    size = ::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status));
+    if (size < 0) {
+      DLOGW("Unable to send data over socket %s", ::strerror(errno));
+      ret = -EFAULT;
+    } else {
+      size = ::read(socket_fd_, response, kSocketCMDMaxLength);
+      if (size < 0) {
+        DLOGW("Unable to read data over socket %s", ::strerror(errno));
+        ret = -EFAULT;
+      } else if (!strncmp(response, cmds.running, strlen(cmds.running))) {
+        *was_running = true;
+      }
+    }
+
+    if (*was_running) {  // if was running, it's requested to disable it.
+      size = ::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off));
+      if (size < 0) {
+        DLOGW("Unable to send data over socket %s", ::strerror(errno));
+        ret = -EFAULT;
+      }
+    }
+  } else {  // if was running, need enable it back.
+    if (*was_running) {
+      size = ::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on));
+      if (size < 0) {
+        DLOGW("Unable to send data over socket %s", ::strerror(errno));
+        ret = -EFAULT;
+      }
+    }
+  }
+
+  return ret;
+}
+
+int HWCQDCMModeManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
+  int ret = 0;
+
+  ret = EnableActiveFeatures((enable ? false : true), kActiveFeatureCMD[kCABLFeature],
+                             &cabl_was_running_);
+  ret = AcquireAndroidWakeLock(enable);
+
+  // if enter QDCM mode, disable GPU fallback idle timeout.
+  if (hwc_display) {
+    uint32_t timeout = enable ? 0 : entry_timeout_;
+    hwc_display->SetIdleTimeoutMs(timeout);
+  }
+
+  return ret;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc/hwc_color_manager.h b/sdm845/sdm/libs/hwc/hwc_color_manager.h
new file mode 100644
index 0000000..20d2b39
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_color_manager.h
@@ -0,0 +1,149 @@
+/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* 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_COLOR_MANAGER_H__
+#define __HWC_COLOR_MANAGER_H__
+
+#include <stdlib.h>
+#include <binder/Parcel.h>
+#include <powermanager/IPowerManager.h>
+#include <binder/BinderService.h>
+#include <core/sdm_types.h>
+#include <utils/locker.h>
+#include <utils/sys.h>
+
+namespace sdm {
+
+// This macro defines name for display APIs interface wrapper library.
+// This macro shall be used to load library using dlopen().
+#define DISPLAY_API_INTERFACE_LIBRARY_NAME "libsdm-disp-vndapis.so"
+
+// This macro defines variable name of display color APIs function tables
+// This macro shall be used to specify name of the variable in dlsym().
+#define DISPLAY_API_FUNC_TABLES "display_color_apis_ftables"
+#define QDCM_DIAG_CLIENT_LIBRARY_NAME "libsdm-diag.so"
+#define INIT_QDCM_DIAG_CLIENT_NAME "QDCMDiagInit"
+#define DEINIT_QDCM_DIAG_CLIENT_NAME "QDCMDiagDeInit"
+
+typedef int (*QDCMDiagInit)(void *ftables);
+
+typedef int (*QDCMDiagDeInit)(void);
+
+// Class to encapsulte all details of managing QDCM operating mode.
+class HWCQDCMModeManager {
+ public:
+  static const uint32_t kSocketCMDMaxLength = 4096;
+  static const uint32_t kFullWakeLock = 0x0000001a;
+  static const uint32_t kAcquireCauseWakeup = 0x10000000;
+  static const uint32_t kONAfterRelease = 0x20000000;
+  enum ActiveFeatureID {
+    kCABLFeature,
+    kADFeature,
+    kSVIFeature,
+    kMaxNumActiveFeature,
+  };
+
+  struct ActiveFeatureCMD {
+    const char *cmd_on = NULL;
+    const char *cmd_off = NULL;
+    const char *cmd_query_status = NULL;
+    const char *running = NULL;
+    ActiveFeatureCMD(const char *arg1, const char *arg2, const char *arg3, const char *arg4)
+        : cmd_on(arg1), cmd_off(arg2), cmd_query_status(arg3), running(arg4) {}
+  };
+
+  static const ActiveFeatureCMD kActiveFeatureCMD[kMaxNumActiveFeature];
+
+ public:
+  static HWCQDCMModeManager *CreateQDCMModeMgr();
+  ~HWCQDCMModeManager();
+  int EnableQDCMMode(bool enable, HWCDisplay *hwc_display);
+
+ protected:
+  bool SendSocketCmd();
+  int AcquireAndroidWakeLock(bool enable);
+  int EnableActiveFeatures(bool enable);
+  int EnableActiveFeatures(bool enable, const ActiveFeatureCMD &cmds, bool *was_running);
+
+ private:
+  bool cabl_was_running_ = false;
+  int socket_fd_ = -1;
+  android::sp<android::IBinder> wakelock_token_ = NULL;
+  android::sp<android::IPowerManager> power_mgr_ = NULL;
+  uint32_t entry_timeout_ = 0;
+  static const char *const kSocketName;
+  static const char *const kTagName;
+  static const char *const kPackageName;
+};
+
+// Class to encapsulte all HWC/OS specific behaviours for ColorManager.
+class HWCColorManager {
+ public:
+  static const int kNumSolidFillLayers = 2;
+  static HWCColorManager *CreateColorManager();
+  static int CreatePayloadFromParcel(const android::Parcel &in, uint32_t *disp_id,
+                                     PPDisplayAPIPayload *sink);
+  static void MarshallStructIntoParcel(const PPDisplayAPIPayload &data,
+                                       android::Parcel *out_parcel);
+
+  ~HWCColorManager();
+  void DestroyColorManager();
+  int EnableQDCMMode(bool enable, HWCDisplay *hwc_display);
+  int SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display);
+  bool SolidFillLayersPrepare(hwc_display_contents_1_t **displays, HWCDisplay *hwc_display);
+  bool SolidFillLayersSet(hwc_display_contents_1_t **displays, HWCDisplay *hwc_display);
+  int SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display);
+  int SetDetailedEnhancer(void *params, HWCDisplay *hwc_display);
+  void SetColorModeDetailEnhancer(HWCDisplay *hwc_display);
+  int SetHWDetailedEnhancerConfig(void *params, HWCDisplay *hwc_display);
+
+ protected:
+  int CreateSolidFillLayers(HWCDisplay *hwc_display);
+  void DestroySolidFillLayers();
+  static uint32_t Get8BitsARGBColorValue(const PPColorFillParams &params);
+
+ private:
+  DynLib color_apis_lib_;
+  DynLib diag_client_lib_;
+  void *color_apis_ = NULL;
+  QDCMDiagInit qdcm_diag_init_ = NULL;
+  QDCMDiagDeInit qdcm_diag_deinit_ = NULL;
+  HWCQDCMModeManager *qdcm_mode_mgr_ = NULL;
+
+  bool solid_fill_enable_ = false;
+  PPColorFillParams solid_fill_params_;
+  hwc_display_contents_1_t *solid_fill_layers_ = NULL;
+  HWCBufferAllocator *buffer_allocator_ = NULL;
+  BufferInfo buffer_info;
+  Locker locker_;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_COLOR_MANAGER_H__
diff --git a/sdm845/sdm/libs/hwc/hwc_debugger.cpp b/sdm845/sdm/libs/hwc/hwc_debugger.cpp
new file mode 100644
index 0000000..0cc0501
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_debugger.cpp
@@ -0,0 +1,199 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <cutils/properties.h>
+
+#include "hwc_debugger.h"
+
+namespace sdm {
+
+HWCDebugHandler HWCDebugHandler::debug_handler_;
+std::bitset<32> HWCDebugHandler::debug_flags_ = 0x1;
+int32_t HWCDebugHandler::verbose_level_ = 0x0;
+
+void HWCDebugHandler::DebugAll(bool enable, int verbose_level) {
+  if (enable) {
+    debug_flags_ = 0x7FFFFFFF;
+    verbose_level_ = verbose_level;
+  } else {
+    debug_flags_ = 0x1;   // kTagNone should always be printed.
+    verbose_level_ = 0;
+  }
+}
+
+void HWCDebugHandler::DebugResources(bool enable, int verbose_level) {
+  if (enable) {
+    debug_flags_[kTagResources] = 1;
+    verbose_level_ = verbose_level;
+  } else {
+    debug_flags_[kTagResources] = 0;
+    verbose_level_ = 0;
+  }
+}
+
+void HWCDebugHandler::DebugStrategy(bool enable, int verbose_level) {
+  if (enable) {
+    debug_flags_[kTagStrategy] = 1;
+    verbose_level_ = verbose_level;
+  } else {
+    debug_flags_[kTagStrategy] = 0;
+    verbose_level_ = 0;
+  }
+}
+
+void HWCDebugHandler::DebugCompManager(bool enable, int verbose_level) {
+  if (enable) {
+    debug_flags_[kTagCompManager] = 1;
+    verbose_level_ = verbose_level;
+  } else {
+    debug_flags_[kTagCompManager] = 0;
+    verbose_level_ = 0;
+  }
+}
+
+void HWCDebugHandler::DebugDriverConfig(bool enable, int verbose_level) {
+  if (enable) {
+    debug_flags_[kTagDriverConfig] = 1;
+    verbose_level_ = verbose_level;
+  } else {
+    debug_flags_[kTagDriverConfig] = 0;
+    verbose_level_ = 0;
+  }
+}
+
+void HWCDebugHandler::DebugRotator(bool enable, int verbose_level) {
+  if (enable) {
+    debug_flags_[kTagRotator] = 1;
+    verbose_level_ = verbose_level;
+  } else {
+    debug_flags_[kTagRotator] = 0;
+    verbose_level_ = 0;
+  }
+}
+
+void HWCDebugHandler::DebugQdcm(bool enable, int verbose_level) {
+  if (enable) {
+    debug_flags_[kTagQDCM] = 1;
+    verbose_level_ = verbose_level;
+  } else {
+    debug_flags_[kTagQDCM] = 0;
+    verbose_level_ = 0;
+  }
+}
+
+void HWCDebugHandler::Error(DebugTag tag, const char *format, ...) {
+  if (debug_flags_[tag]) {
+    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, ...) {
+  if (debug_flags_[tag]) {
+    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 (debug_flags_[tag]) {
+    va_list list;
+    va_start(list, format);
+    __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, list);
+  }
+}
+
+void HWCDebugHandler::Debug(DebugTag tag, const char *format, ...) {
+  if (debug_flags_[tag]) {
+    va_list list;
+    va_start(list, format);
+    __android_log_vprint(ANDROID_LOG_DEBUG, LOG_TAG, format, list);
+  }
+}
+
+void HWCDebugHandler::Verbose(DebugTag tag, const char *format, ...) {
+  if (debug_flags_[tag] && verbose_level_) {
+    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) {
+  if (atrace_is_tag_enabled(ATRACE_TAG)) {
+    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);
+}
+
+int  HWCDebugHandler::GetIdleTimeoutMs() {
+  int value = IDLE_TIMEOUT_DEFAULT_MS;
+  debug_handler_.GetProperty("sdm.idle_time", &value);
+
+  return value;
+}
+
+DisplayError HWCDebugHandler::GetProperty(const char *property_name, int *value) {
+  char property[PROPERTY_VALUE_MAX];
+
+  if (property_get(property_name, property, NULL) > 0) {
+    *value = atoi(property);
+    return kErrorNone;
+  }
+
+  return kErrorNotSupported;
+}
+
+DisplayError HWCDebugHandler::GetProperty(const char *property_name, char *value) {
+  if (property_get(property_name, value, NULL) > 0) {
+    return kErrorNone;
+  }
+
+  return kErrorNotSupported;
+}
+
+DisplayError HWCDebugHandler::SetProperty(const char *property_name, const char *value) {
+  if (property_set(property_name, value) == 0) {
+    return kErrorNone;
+  }
+
+  return kErrorNotSupported;
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/hwc/hwc_debugger.h b/sdm845/sdm/libs/hwc/hwc_debugger.h
new file mode 100644
index 0000000..01319ab
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_debugger.h
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __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>
+#include <bitset>
+
+namespace sdm {
+
+class HWCDebugHandler : public DebugHandler {
+ public:
+  static inline DebugHandler* Get() { return &debug_handler_; }
+
+  static void DebugAll(bool enable, int verbose_level);
+  static void DebugResources(bool enable, int verbose_level);
+  static void DebugStrategy(bool enable, int verbose_level);
+  static void DebugCompManager(bool enable, int verbose_level);
+  static void DebugDriverConfig(bool enable, int verbose_level);
+  static void DebugRotator(bool enable, int verbose_level);
+  static void DebugQdcm(bool enable, int verbose_level);
+  static int  GetIdleTimeoutMs();
+
+  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 Debug(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();
+  virtual DisplayError GetProperty(const char *property_name, int *value);
+  virtual DisplayError GetProperty(const char *property_name, char *value);
+  virtual DisplayError SetProperty(const char *property_name, const char *value);
+
+ private:
+  static HWCDebugHandler debug_handler_;
+  static std::bitset<32> debug_flags_;
+  static int32_t verbose_level_;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_DEBUGGER_H__
+
diff --git a/sdm845/sdm/libs/hwc/hwc_display.cpp b/sdm845/sdm/libs/hwc/hwc_display.cpp
new file mode 100644
index 0000000..2c5c885
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_display.cpp
@@ -0,0 +1,1536 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <gr.h>
+#include <utils/constants.h>
+#include <utils/formats.h>
+#include <utils/rect.h>
+#include <utils/debug.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sync/sync.h>
+#include <cutils/properties.h>
+#include <qd_utils.h>
+#include <map>
+#include <utility>
+#include <vector>
+#include <string>
+
+#include "blit_engine_c2d.h"
+#include "hwc_debugger.h"
+#include "hwc_display.h"
+#include "hwc_tonemapper.h"
+
+#ifdef QTI_BSP
+#include <hardware/display_defs.h>
+#endif
+
+#define __CLASS__ "HWCDisplay"
+
+namespace sdm {
+
+void HWCColorMode::Init() {
+  int ret = PopulateColorModes();
+  if (ret != 0) {
+    DLOGW("Failed!!");
+  }
+  return;
+}
+
+int HWCColorMode::SetColorMode(const std::string &color_mode) {
+  if (color_modes_.empty()) {
+    DLOGW("No Color Modes supported");
+    return -1;
+  }
+
+  std::vector<std::string>::iterator it = std::find(color_modes_.begin(), color_modes_.end(),
+                                                    color_mode);
+  if (it == color_modes_.end()) {
+    DLOGE("Invalid colorMode request: %s", color_mode.c_str());
+    return -1;
+  }
+
+  DisplayError error = display_intf_->SetColorMode(color_mode);
+  if (error != kErrorNone) {
+    DLOGE("Failed to set color_mode = %s", color_mode.c_str());
+    return -1;
+  }
+  current_color_mode_ = color_mode;
+
+  return 0;
+}
+
+const std::vector<std::string> &HWCColorMode::GetColorModes() {
+  return color_modes_;
+}
+
+int HWCColorMode::SetColorTransform(uint32_t matrix_count, const float *matrix) {
+  if (matrix_count > kColorTransformMatrixCount) {
+    DLOGE("Transform matrix count = %d, exceeds max = %d", matrix_count,
+          kColorTransformMatrixCount);
+    return -1;
+  }
+
+  double color_matrix[kColorTransformMatrixCount] = {0};
+  CopyColorTransformMatrix(matrix, color_matrix);
+  DisplayError error = display_intf_->SetColorTransform(matrix_count, color_matrix);
+  if (error != kErrorNone) {
+    DLOGE("Failed!");
+    return -1;
+  }
+
+  return 0;
+}
+
+int HWCColorMode::PopulateColorModes() {
+  uint32_t color_mode_count = 0;
+  DisplayError error = display_intf_->GetColorModeCount(&color_mode_count);
+  if (error != kErrorNone || (color_mode_count == 0)) {
+    return -1;
+  }
+
+  DLOGI("Color Mode count = %d", color_mode_count);
+
+  color_modes_.resize(color_mode_count);
+
+  // SDM returns modes which is string
+  error = display_intf_->GetColorModes(&color_mode_count, &color_modes_);
+  if (error != kErrorNone) {
+    DLOGE("GetColorModes Failed for count = %d", color_mode_count);
+    return -1;
+  }
+
+  return 0;
+}
+
+HWCDisplay::HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type,
+                       int id, bool needs_blit, qService::QService *qservice,
+                       DisplayClass display_class)
+  : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), needs_blit_(needs_blit),
+    qservice_(qservice), display_class_(display_class) {
+}
+
+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;
+  }
+
+  HWCDebugHandler::Get()->GetProperty("sys.hwc_disable_hdr", &disable_hdr_handling_);
+  if (disable_hdr_handling_) {
+    DLOGI("HDR Handling disabled");
+  }
+
+  int property_swap_interval = 1;
+  HWCDebugHandler::Get()->GetProperty("debug.egl.swapinterval", &property_swap_interval);
+  if (property_swap_interval == 0) {
+    swap_interval_zero_ = true;
+  }
+
+  int blit_enabled = 0;
+  HWCDebugHandler::Get()->GetProperty("persist.hwc.blit.comp", &blit_enabled);
+  if (needs_blit_ && blit_enabled) {
+    blit_engine_ = new BlitEngineC2d();
+    if (!blit_engine_) {
+      DLOGI("Create Blit Engine C2D failed");
+    } else {
+      if (blit_engine_->Init() < 0) {
+        DLOGI("Blit Engine Init failed, Blit Composition will not be used!!");
+        delete blit_engine_;
+        blit_engine_ = NULL;
+      }
+    }
+  }
+
+  tone_mapper_ = new HWCToneMapper();
+
+  display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
+  current_refresh_rate_ = max_refresh_rate_;
+
+  s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_NO_3D, kS3dFormatNone));
+  s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_3D_SIDE_BY_SIDE_L_R,
+                                kS3dFormatLeftRight));
+  s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_3D_SIDE_BY_SIDE_R_L,
+                                kS3dFormatRightLeft));
+  s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_3D_TOP_BOTTOM,
+                                kS3dFormatTopBottom));
+
+  disable_animation_ = Debug::IsExtAnimDisabled();
+
+  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 (blit_engine_) {
+    blit_engine_->DeInit();
+    delete blit_engine_;
+    blit_engine_ = NULL;
+  }
+
+  delete tone_mapper_;
+  tone_mapper_ = NULL;
+
+  return 0;
+}
+
+int HWCDisplay::EventControl(int event, int enable) {
+  DisplayError error = kErrorNone;
+
+  if (shutdown_pending_) {
+    return 0;
+  }
+
+  switch (event) {
+  case HWC_EVENT_VSYNC:
+    error = display_intf_->SetVSyncState(enable);
+    break;
+  default:
+    DLOGW("Unsupported event = %d", event);
+  }
+
+  if (error != kErrorNone) {
+    if (error == kErrorShutDown) {
+      shutdown_pending_ = true;
+      return 0;
+    }
+    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;
+  bool flush_on_error = flush_on_error_;
+
+  if (shutdown_pending_) {
+    return 0;
+  }
+
+  switch (mode) {
+  case HWC_POWER_MODE_OFF:
+    // During power off, all of the buffers are released.
+    // Do not flush until a buffer is successfully submitted again.
+    flush_on_error = false;
+    state = kStateOff;
+    tone_mapper_->Terminate();
+    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) {
+    flush_on_error_ = flush_on_error;
+  } else {
+    if (error == kErrorShutDown) {
+      shutdown_pending_ = true;
+      return 0;
+    }
+    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 *display_attributes,
+                                     int32_t *values) {
+  DisplayConfigVariableInfo variable_config;
+  DisplayError error = display_intf_->GetFrameBufferConfig(&variable_config);
+  if (error != kErrorNone) {
+    DLOGV("Get variable config failed. Error = %d", error);
+    return -EINVAL;
+  }
+
+  for (int i = 0; display_attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
+    switch (display_attributes[i]) {
+    case HWC_DISPLAY_VSYNC_PERIOD:
+      values[i] = INT32(variable_config.vsync_period_ns);
+      break;
+    case HWC_DISPLAY_WIDTH:
+      values[i] = INT32(variable_config.x_pixels);
+      break;
+    case HWC_DISPLAY_HEIGHT:
+      values[i] = INT32(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;
+    default:
+      DLOGW("Spurious attribute type = %d", display_attributes[i]);
+      return -EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+int HWCDisplay::GetActiveConfig() {
+  return 0;
+}
+
+int HWCDisplay::SetActiveConfig(int index) {
+  return -1;
+}
+
+DisplayError HWCDisplay::SetMixerResolution(uint32_t width, uint32_t height) {
+  return kErrorNotSupported;
+}
+
+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);
+
+  if (blit_engine_) {
+    blit_engine_->SetFrameDumpConfig(count);
+  }
+
+  if (tone_mapper_) {
+    tone_mapper_->SetFrameDumpConfig(count);
+  }
+
+  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) {
+  const hwc_procs_t *hwc_procs = *hwc_procs_;
+
+  if (!hwc_procs) {
+    return kErrorParameters;
+  }
+
+  hwc_procs->vsync(hwc_procs, id_, vsync.timestamp);
+
+  return kErrorNone;
+}
+
+DisplayError HWCDisplay::Refresh() {
+  return kErrorNotSupported;
+}
+
+DisplayError HWCDisplay::CECMessage(char *message) {
+  if (qservice_) {
+    qservice_->onCECMessageReceived(message, 0);
+  } else {
+    DLOGW("Qservice instance not available.");
+  }
+
+  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;
+  uint32_t blit_target_count = 0;
+
+  if (blit_engine_) {
+    blit_target_count = kMaxBlitTargetLayers;
+  }
+
+  FreeLayerStack();
+
+  for (size_t i = 0; i < num_hw_layers + blit_target_count; i++) {
+    Layer *layer = new Layer();
+    layer_stack_.layers.push_back(layer);
+  }
+
+  return 0;
+}
+
+void HWCDisplay::FreeLayerStack() {
+  for (Layer *layer : layer_stack_.layers) {
+    delete layer;
+  }
+  layer_stack_ = {};
+}
+
+int HWCDisplay::PrepareLayerParams(hwc_layer_1_t *hwc_layer, Layer* layer) {
+  const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer->handle);
+
+  LayerBuffer &layer_buffer = layer->input_buffer;
+
+  if (pvt_handle) {
+    layer_buffer.planes[0].fd = pvt_handle->fd;
+    layer_buffer.format = GetSDMFormat(pvt_handle->format, pvt_handle->flags);
+    int aligned_width, aligned_height;
+    int unaligned_width, unaligned_height;
+
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(pvt_handle, aligned_width,
+                                                          aligned_height);
+    AdrenoMemInfo::getInstance().getUnalignedWidthAndHeight(pvt_handle, unaligned_width,
+                                                            unaligned_height);
+
+    layer_buffer.width = UINT32(aligned_width);
+    layer_buffer.height = UINT32(aligned_height);
+    layer_buffer.unaligned_width = UINT32(unaligned_width);
+    layer_buffer.unaligned_height = UINT32(unaligned_height);
+
+    if (SetMetaData(pvt_handle, layer) != kErrorNone) {
+      return -EINVAL;
+    }
+
+    if (pvt_handle->bufferType == BUFFER_TYPE_VIDEO) {
+      layer_stack_.flags.video_present = true;
+      layer_buffer.flags.video = true;
+    }
+    // TZ Protected Buffer - L1
+    if (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+      layer_stack_.flags.secure_present = true;
+      layer_buffer.flags.secure = true;
+      if (pvt_handle->flags & private_handle_t::PRIV_FLAGS_CAMERA_WRITE) {
+        layer_buffer.flags.secure_camera = true;
+      }
+    }
+    // Gralloc Usage Protected Buffer - L3 - which needs to be treated as Secure & avoid fallback
+    if (pvt_handle->flags & private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER) {
+      layer_stack_.flags.secure_present = true;
+    }
+    if (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
+      layer_buffer.flags.secure_display = true;
+    }
+
+    // check if this is special solid_fill layer without input_buffer.
+    if (solid_fill_enable_ && pvt_handle->fd == -1) {
+      layer->flags.solid_fill = true;
+      layer->solid_fill_color = solid_fill_color_;
+    }
+  } else {
+    // for FBT layer
+    if (hwc_layer->compositionType == HWC_FRAMEBUFFER_TARGET) {
+      uint32_t x_pixels;
+      uint32_t y_pixels;
+      int aligned_width;
+      int aligned_height;
+      int usage = GRALLOC_USAGE_HW_FB;
+      int format = HAL_PIXEL_FORMAT_RGBA_8888;
+      int ubwc_enabled = 0;
+      int flags = 0;
+      HWCDebugHandler::Get()->GetProperty("debug.gralloc.enable_fb_ubwc", &ubwc_enabled);
+      bool linear = layer_stack_.output_buffer && !IsUBWCFormat(layer_stack_.output_buffer->format);
+      if ((ubwc_enabled == 1) && !linear) {
+        usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+        flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+      }
+
+      GetFrameBufferResolution(&x_pixels, &y_pixels);
+
+      AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(INT(x_pixels), INT(y_pixels), format,
+                                                            usage, aligned_width, aligned_height);
+      layer_buffer.width = UINT32(aligned_width);
+      layer_buffer.height = UINT32(aligned_height);
+      layer_buffer.unaligned_width = x_pixels;
+      layer_buffer.unaligned_height = y_pixels;
+      layer_buffer.format = GetSDMFormat(format, flags);
+    }
+  }
+
+  return 0;
+}
+
+void HWCDisplay::CommitLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer) {
+  const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer->handle);
+  LayerBuffer &layer_buffer = layer->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 = UINT32(pvt_handle->width);
+    layer_buffer.size = pvt_handle->size;
+  }
+
+  // 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;
+}
+
+int HWCDisplay::PrePrepareLayerStack(hwc_display_contents_1_t *content_list) {
+  if (shutdown_pending_) {
+    return 0;
+  }
+
+  size_t num_hw_layers = content_list->numHwLayers;
+
+  use_blit_comp_ = false;
+  metadata_refresh_rate_ = 0;
+  display_rect_ = LayerRect();
+
+  // 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.at(i);
+    int ret = PrepareLayerParams(&content_list->hwLayers[i], layer);
+
+    if (ret != kErrorNone) {
+      return ret;
+    }
+
+    layer->flags.skip = ((hwc_layer.flags & HWC_SKIP_LAYER) > 0);
+    layer->flags.solid_fill = (hwc_layer.flags & kDimLayer) || solid_fill_enable_;
+    if (layer->flags.skip || layer->flags.solid_fill) {
+      layer->dirty_regions.clear();
+    }
+
+    hwc_rect_t scaled_display_frame = hwc_layer.displayFrame;
+    ApplyScanAdjustment(&scaled_display_frame);
+
+    SetRect(scaled_display_frame, &layer->dst_rect);
+    if (pvt_handle) {
+        bool NonIntegralSourceCrop =  IsNonIntegralSourceCrop(hwc_layer.sourceCropf);
+        bool secure = (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) ||
+                (pvt_handle->flags & private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER) ||
+                (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY);
+        if (NonIntegralSourceCrop && (!secure && pvt_handle->bufferType != BUFFER_TYPE_VIDEO)) {
+            layer->flags.skip = true;
+        }
+    }
+    SetRect(hwc_layer.sourceCropf, &layer->src_rect);
+
+    uint32_t num_visible_rects = UINT32(hwc_layer.visibleRegionScreen.numRects);
+    uint32_t num_dirty_rects = UINT32(hwc_layer.surfaceDamage.numRects);
+
+    for (uint32_t j = 0; j < num_visible_rects; j++) {
+      LayerRect visible_rect = {};
+      SetRect(hwc_layer.visibleRegionScreen.rects[j], &visible_rect);
+      layer->visible_regions.push_back(visible_rect);
+    }
+
+    for (uint32_t j = 0; j < num_dirty_rects; j++) {
+      LayerRect dirty_rect = {};
+      SetRect(hwc_layer.surfaceDamage.rects[j], &dirty_rect);
+      layer->dirty_regions.push_back(dirty_rect);
+    }
+
+    if (blit_engine_) {
+      for (uint32_t j = 0; j < kMaxBlitTargetLayers; j++) {
+        LayerRect blit_rect = {};
+        layer->blit_regions.push_back(blit_rect);
+      }
+    }
+
+    SetComposition(hwc_layer.compositionType, &layer->composition);
+    if (hwc_layer.compositionType != HWC_FRAMEBUFFER_TARGET) {
+      display_rect_ = Union(display_rect_, layer->dst_rect);
+    }
+
+    // For dim layers, SurfaceFlinger
+    //    - converts planeAlpha to per pixel alpha,
+    //    - sets appropriate RGB color,
+    //    - sets planeAlpha to 0xff,
+    //    - blending to Premultiplied.
+    // This can be achieved at hardware by
+    //    - solid fill ARGB to appropriate value,
+    //    - incoming planeAlpha,
+    //    - blending to Coverage.
+    if (hwc_layer.flags & kDimLayer) {
+      layer->input_buffer.format = kFormatARGB8888;
+      layer->solid_fill_color = 0xff000000;
+#ifdef QTI_BSP
+      // Get ARGB color from HWC Dim Layer color
+      uint32_t a = UINT32(hwc_layer.color.a) << 24;
+      uint32_t r = UINT32(hwc_layer.color.r) << 16;
+      uint32_t g = UINT32(hwc_layer.color.g) << 8;
+      uint32_t b = UINT32(hwc_layer.color.b);
+      layer->solid_fill_color = a | r | g | b;
+#endif
+      SetBlending(HWC_BLENDING_COVERAGE, &layer->blending);
+    } else {
+      SetBlending(hwc_layer.blending, &layer->blending);
+      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);
+    }
+
+    // TODO(user): Remove below block.
+    // For solid fill, only dest rect need to be specified.
+    if (layer->flags.solid_fill) {
+      LayerBuffer &input_buffer = layer->input_buffer;
+      input_buffer.width = UINT32(layer->dst_rect.right - layer->dst_rect.left);
+      input_buffer.height = UINT32(layer->dst_rect.bottom - layer->dst_rect.top);
+      input_buffer.unaligned_width = input_buffer.width;
+      input_buffer.unaligned_height = input_buffer.height;
+      layer->src_rect.left = 0;
+      layer->src_rect.top = 0;
+      layer->src_rect.right = input_buffer.width;
+      layer->src_rect.bottom = input_buffer.height;
+    }
+
+    layer->plane_alpha = hwc_layer.planeAlpha;
+    layer->flags.cursor = ((hwc_layer.flags & HWC_IS_CURSOR_LAYER) > 0);
+    layer->flags.updating = true;
+
+    if (num_hw_layers <= kMaxLayerCount) {
+      layer->flags.updating = IsLayerUpdating(content_list, layer);
+    }
+#ifdef QTI_BSP
+    if (hwc_layer.flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
+      layer_stack_.flags.animating = true;
+    }
+#endif
+    if (layer->flags.skip) {
+      layer_stack_.flags.skip_present = true;
+    }
+
+    if (layer->flags.cursor) {
+      layer_stack_.flags.cursor_present = true;
+    }
+
+    PrepareDynamicRefreshRate(layer);
+
+    layer->input_buffer.buffer_id = reinterpret_cast<uint64_t>(hwc_layer.handle);
+  }
+
+  // Prepare the Blit Target
+  if (blit_engine_) {
+  // TODO(user): Fix this to enable BLIT
+#if 0
+    int ret = blit_engine_->Prepare(&layer_stack_);
+    if (ret) {
+      // Blit engine cannot handle this layer stack, hence set the layer stack
+      // count to num_hw_layers
+      layer_stack_.layer_count -= kMaxBlitTargetLayers;
+    } else {
+      use_blit_comp_ = true;
+    }
+#endif
+  }
+
+  // Configure layer stack
+  layer_stack_.flags.geometry_changed = ((content_list->flags & HWC_GEOMETRY_CHANGED) > 0);
+
+  return 0;
+}
+
+void HWCDisplay::SetLayerS3DMode(const LayerBufferS3DFormat &source, uint32_t *target) {
+#ifdef QTI_BSP
+    switch (source) {
+    case kS3dFormatNone: *target = HWC_S3DMODE_NONE; break;
+    case kS3dFormatLeftRight: *target = HWC_S3DMODE_LR; break;
+    case kS3dFormatRightLeft: *target = HWC_S3DMODE_RL; break;
+    case kS3dFormatTopBottom: *target = HWC_S3DMODE_TB; break;
+    case kS3dFormatFramePacking: *target = HWC_S3DMODE_FP; break;
+    default: *target = HWC_S3DMODE_MAX; break;
+    }
+#endif
+}
+
+int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
+  if (shutdown_pending_) {
+    return 0;
+  }
+
+  size_t num_hw_layers = content_list->numHwLayers;
+
+  if (!skip_prepare_cnt) {
+    DisplayError error = display_intf_->Prepare(&layer_stack_);
+    if (error != kErrorNone) {
+      if (error == kErrorShutDown) {
+        shutdown_pending_ = true;
+      } else if ((error != kErrorPermission) && (error != kErrorNoAppLayers)) {
+        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;
+      } else {
+        DLOGV("Prepare failed for Display = %d Error = %d", type_, error);
+      }
+      return 0;
+    }
+  } else {
+    // Skip is not set
+    MarkLayersForGPUBypass(content_list);
+    skip_prepare_cnt = skip_prepare_cnt - 1;
+    DLOGI("SecureDisplay %s, Skip Prepare/Commit and Flush", secure_display_active_ ? "Starting" :
+          "Stopping");
+    flush_ = true;
+  }
+
+  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.at(i);
+    LayerComposition composition = layer->composition;
+    private_handle_t* pvt_handle  = static_cast<private_handle_t*>
+      (const_cast<native_handle_t*>(hwc_layer.handle));
+    MetaData_t *meta_data = pvt_handle ?
+      reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata) : NULL;
+
+    if ((composition == kCompositionSDE) || (composition == kCompositionHybrid) ||
+        (composition == kCompositionBlit)) {
+      hwc_layer.hints |= HWC_HINT_CLEAR_FB;
+    }
+    SetComposition(composition, &hwc_layer.compositionType);
+
+    if (meta_data != NULL) {
+      if (composition == kCompositionGPUS3D) {
+        // Align HWC and client's dispaly ID in case of HDMI as primary
+        meta_data->s3dComp.displayId =
+          display_intf_->IsPrimaryDisplay() ? HWC_DISPLAY_PRIMARY: id_;
+        SetLayerS3DMode(layer->input_buffer.s3d_format,
+            &meta_data->s3dComp.s3dMode);
+      }
+    }
+  }
+
+  return 0;
+}
+
+int HWCDisplay::CommitLayerStack(hwc_display_contents_1_t *content_list) {
+  if (!content_list || !content_list->numHwLayers) {
+    DLOGW("Invalid content list");
+    return -EINVAL;
+  }
+
+  if (shutdown_pending_) {
+    return 0;
+  }
+
+  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++) {
+      CommitLayerParams(&content_list->hwLayers[i], layer_stack_.layers.at(i));
+    }
+
+    if (use_blit_comp_) {
+      status = blit_engine_->PreCommit(content_list, &layer_stack_);
+      if (status == 0) {
+        status = blit_engine_->Commit(content_list, &layer_stack_);
+        if (status != 0) {
+          DLOGE("Blit Comp Failed!");
+        }
+      }
+    }
+
+    if (layer_stack_.flags.hdr_present) {
+      status = tone_mapper_->HandleToneMap(content_list, &layer_stack_);
+      if (status != 0) {
+        DLOGE("Error handling HDR in ToneMapper");
+      }
+    } else {
+      tone_mapper_->Terminate();
+    }
+
+    DisplayError error = kErrorUndefined;
+    if (status == 0) {
+      error = display_intf_->Commit(&layer_stack_);
+      status = 0;
+    }
+
+    if (error == kErrorNone) {
+      // A commit is successfully submitted, start flushing on failure now onwards.
+      flush_on_error_ = true;
+    } else {
+      if (error == kErrorShutDown) {
+        shutdown_pending_ = true;
+        return status;
+      } else if (error != kErrorPermission) {
+        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;
+      } else {
+        DLOGI("Commit failed for Display = %d Error = %d", type_, error);
+      }
+    }
+  }
+
+  return status;
+}
+
+int HWCDisplay::PostCommitLayerStack(hwc_display_contents_1_t *content_list) {
+  size_t num_hw_layers = content_list->numHwLayers;
+  int status = 0;
+
+  // Do no call flush on errors, if a successful buffer is never submitted.
+  if (flush_ && flush_on_error_) {
+    display_intf_->Flush();
+  }
+
+
+  if (tone_mapper_ && tone_mapper_->IsActive()) {
+     tone_mapper_->PostCommit(&layer_stack_);
+  }
+
+  // Set the release fence fd to the blit engine
+  if (use_blit_comp_ && blit_engine_->BlitActive()) {
+    blit_engine_->PostCommit(&layer_stack_);
+  }
+
+  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.at(i);
+    LayerBuffer &layer_buffer = layer->input_buffer;
+
+    if (!flush_) {
+      // If swapinterval property is set to 0 or for single buffer layers, do not update f/w
+      // release fences and discard fences from driver
+      if (swap_interval_zero_ || layer->flags.single_buffer) {
+        hwc_layer.releaseFenceFd = -1;
+        close(layer_buffer.release_fence_fd);
+        layer_buffer.release_fence_fd = -1;
+      } else 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 (disable_animation_) {
+        if (layer->composition == kCompositionGPUTarget && animating_) {
+          close(hwc_layer.releaseFenceFd);
+          hwc_layer.releaseFenceFd = -1;
+        }
+      }
+    }
+
+    if (hwc_layer.acquireFenceFd >= 0) {
+      close(hwc_layer.acquireFenceFd);
+      hwc_layer.acquireFenceFd = -1;
+    }
+  }
+
+  if (!flush_) {
+    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::IsLayerUpdating(hwc_display_contents_1_t *content_list, const Layer *layer) {
+  // Layer should be considered updating if
+  //   a) layer is in single buffer mode, or
+  //   b) valid dirty_regions(android specific hint for updating status), or
+  //   c) layer stack geometry has changed
+  return (layer->flags.single_buffer || IsSurfaceUpdated(layer->dirty_regions) ||
+         (layer_stack_.flags.geometry_changed));
+}
+
+bool HWCDisplay::IsNonIntegralSourceCrop(const hwc_frect_t &source) {
+     if ((source.left != roundf(source.left)) ||
+         (source.top != roundf(source.top)) ||
+         (source.right != roundf(source.right)) ||
+         (source.bottom != roundf(source.bottom))) {
+         return true;
+     } else {
+         return false;
+     }
+}
+
+void HWCDisplay::SetRect(const hwc_rect_t &source, LayerRect *target) {
+  target->left = FLOAT(source.left);
+  target->top = FLOAT(source.top);
+  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 = kCompositionGPU;        break;
+  }
+}
+
+void HWCDisplay::SetComposition(const LayerComposition &source, int32_t *target) {
+  switch (source) {
+  case kCompositionGPUTarget:   *target = HWC_FRAMEBUFFER_TARGET; break;
+  case kCompositionGPU:         *target = HWC_FRAMEBUFFER;        break;
+  case kCompositionGPUS3D:      *target = HWC_FRAMEBUFFER;        break;
+  case kCompositionCursor:      *target = HWC_CURSOR_OVERLAY;     break;
+  default:                      *target = HWC_OVERLAY;            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) {
+  return;
+}
+
+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_BGR_565:             format = kFormatBGR565Ubwc;              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;
+    case HAL_PIXEL_FORMAT_RGBA_1010102:        format = kFormatRGBA1010102Ubwc;         break;
+    case HAL_PIXEL_FORMAT_RGBX_1010102:        format = kFormatRGBX1010102Ubwc;         break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC: format = kFormatYCbCr420TP10Ubwc;        break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC: format = kFormatYCbCr420P010Ubwc;        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_BGR_565:                  format = kFormatBGR565;                   break;
+  case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:       format = kFormatYCbCr420SemiPlanarVenus;  break;
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:       format = kFormatYCrCb420SemiPlanarVenus;  break;
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:  format = kFormatYCbCr420SPVenusUbwc;      break;
+  case HAL_PIXEL_FORMAT_YV12:                     format = kFormatYCrCb420PlanarStride16;   break;
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP:             format = kFormatYCrCb420SemiPlanar;       break;
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP:             format = kFormatYCbCr420SemiPlanar;       break;
+  case HAL_PIXEL_FORMAT_YCbCr_422_SP:             format = kFormatYCbCr422H2V1SemiPlanar;   break;
+  case HAL_PIXEL_FORMAT_YCbCr_422_I:              format = kFormatYCbCr422H2V1Packed;       break;
+  case HAL_PIXEL_FORMAT_CbYCrY_422_I:             format = kFormatCbYCrY422H2V1Packed;      break;
+  case HAL_PIXEL_FORMAT_RGBA_1010102:             format = kFormatRGBA1010102;              break;
+  case HAL_PIXEL_FORMAT_ARGB_2101010:             format = kFormatARGB2101010;              break;
+  case HAL_PIXEL_FORMAT_RGBX_1010102:             format = kFormatRGBX1010102;              break;
+  case HAL_PIXEL_FORMAT_XRGB_2101010:             format = kFormatXRGB2101010;              break;
+  case HAL_PIXEL_FORMAT_BGRA_1010102:             format = kFormatBGRA1010102;              break;
+  case HAL_PIXEL_FORMAT_ABGR_2101010:             format = kFormatABGR2101010;              break;
+  case HAL_PIXEL_FORMAT_BGRX_1010102:             format = kFormatBGRX1010102;              break;
+  case HAL_PIXEL_FORMAT_XBGR_2101010:             format = kFormatXBGR2101010;              break;
+  case HAL_PIXEL_FORMAT_YCbCr_420_P010:           format = kFormatYCbCr420P010;             break;
+  case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:      format = kFormatYCbCr420TP10Ubwc;         break;
+  case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:      format = kFormatYCbCr420P010Ubwc;         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,
+               qdutils::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");
+    }
+  }
+}
+
+void HWCDisplay::DumpOutputBuffer(const BufferInfo& buffer_info, void *base, int fence) {
+  char dir_path[PATH_MAX];
+
+  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 (base) {
+    char dump_file_name[PATH_MAX];
+    size_t result = 0;
+
+    if (fence >= 0) {
+      int error = sync_wait(fence, 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, buffer_info.alloc_buffer_info.aligned_width,
+             buffer_info.alloc_buffer_info.aligned_height,
+             GetFormatString(buffer_info.buffer_config.format), dump_frame_index_);
+
+    FILE* fp = fopen(dump_file_name, "w+");
+    if (fp) {
+      result = fwrite(base, buffer_info.alloc_buffer_info.size, 1, fp);
+      fclose(fp);
+    }
+
+    DLOGI("Frame Dump of %s is %s", dump_file_name, result ? "Successful" : "Failed");
+  }
+}
+
+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) {
+  DisplayConfigVariableInfo fb_config;
+  DisplayError error = display_intf_->GetFrameBufferConfig(&fb_config);
+  if (error != kErrorNone) {
+    DLOGV("Get frame buffer config failed. Error = %d", error);
+    return -EINVAL;
+  }
+
+  fb_config.x_pixels = x_pixels;
+  fb_config.y_pixels = y_pixels;
+
+  error = display_intf_->SetFrameBufferConfig(fb_config);
+  if (error != kErrorNone) {
+    DLOGV("Set frame buffer config failed. Error = %d", error);
+    return -EINVAL;
+  }
+
+  DLOGI("New framebuffer resolution (%dx%d)", x_pixels, y_pixels);
+
+  return 0;
+}
+
+void HWCDisplay::GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+  DisplayConfigVariableInfo fb_config;
+  display_intf_->GetFrameBufferConfig(&fb_config);
+
+  *x_pixels = fb_config.x_pixels;
+  *y_pixels = fb_config.y_pixels;
+}
+
+DisplayError HWCDisplay::GetMixerResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+  return display_intf_->GetMixerResolution(x_pixels, y_pixels);
+}
+
+
+void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+  DisplayConfigVariableInfo display_config;
+  uint32_t active_index = 0;
+
+  display_intf_->GetActiveConfig(&active_index);
+  display_intf_->GetConfig(active_index, &display_config);
+
+  *x_pixels = display_config.x_pixels;
+  *y_pixels = display_config.y_pixels;
+}
+
+int HWCDisplay::SetDisplayStatus(uint32_t display_status) {
+  int status = 0;
+  const hwc_procs_t *hwc_procs = *hwc_procs_;
+
+  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;
+  }
+
+  if (display_status == kDisplayStatusResume ||
+      display_status == kDisplayStatusPause) {
+    hwc_procs->invalidate(hwc_procs);
+  }
+
+  return status;
+}
+
+int HWCDisplay::SetCursorPosition(int x, int y) {
+  DisplayError error = kErrorNone;
+
+  if (shutdown_pending_) {
+    return 0;
+  }
+
+  error = display_intf_->SetCursorPosition(x, y);
+  if (error != kErrorNone) {
+    if (error == kErrorShutDown) {
+      shutdown_pending_ = true;
+      return 0;
+    }
+    DLOGE("Failed for x = %d y = %d, Error = %d", x, y, error);
+    return -1;
+  }
+
+  return 0;
+}
+
+int HWCDisplay::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
+  DisplayError error = display_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
+  if (error != kErrorNone) {
+    DLOGE("Failed. Error = %d", error);
+    return -1;
+  }
+
+  return 0;
+}
+
+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::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+}
+
+DisplayError HWCDisplay::SetCSC(const MetaData_t *meta_data, ColorMetaData *color_metadata) {
+  if (meta_data->operation & COLOR_METADATA) {
+#ifdef USE_COLOR_METADATA
+    *color_metadata = meta_data->color;
+#endif
+  } else if (meta_data->operation & UPDATE_COLOR_SPACE) {
+    ColorSpace_t csc = meta_data->colorSpace;
+    color_metadata->range = Range_Limited;
+
+    if (csc == ITU_R_601_FR || csc == ITU_R_2020_FR) {
+      color_metadata->range = Range_Full;
+    }
+
+    switch (csc) {
+    case ITU_R_601:
+    case ITU_R_601_FR:
+      // display driver uses 601 irrespective of 525 or 625
+      color_metadata->colorPrimaries = ColorPrimaries_BT601_6_525;
+      break;
+    case ITU_R_709:
+      color_metadata->colorPrimaries = ColorPrimaries_BT709_5;
+      break;
+    case ITU_R_2020:
+    case ITU_R_2020_FR:
+      color_metadata->colorPrimaries = ColorPrimaries_BT2020;
+      break;
+    default:
+      DLOGE("Unsupported CSC: %d", csc);
+      return kErrorNotSupported;
+    }
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWCDisplay::SetIGC(IGC_t source, LayerIGC *target) {
+  switch (source) {
+  case IGC_NotSpecified:    *target = kIGCNotSpecified; break;
+  case IGC_sRGB:            *target = kIGCsRGB;   break;
+  default:
+    DLOGE("Unsupported IGC: %d", source);
+    return kErrorNotSupported;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWCDisplay::SetMetaData(const private_handle_t *pvt_handle, Layer *layer) {
+  const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata);
+  LayerBuffer &layer_buffer = layer->input_buffer;
+
+  if (!meta_data) {
+    return kErrorNone;
+  }
+
+  if (SetCSC(meta_data, &layer_buffer.color_metadata) != kErrorNone) {
+    return kErrorNotSupported;
+  }
+
+  bool hdr_layer = layer_buffer.color_metadata.colorPrimaries == ColorPrimaries_BT2020 &&
+                   (layer_buffer.color_metadata.transfer == Transfer_SMPTE_ST2084 ||
+                   layer_buffer.color_metadata.transfer == Transfer_HLG);
+  if (hdr_layer && !disable_hdr_handling_) {
+    // dont honor HDR when its handling is disabled
+    layer_buffer.flags.hdr = true;
+    layer_stack_.flags.hdr_present = true;
+  }
+
+  if (meta_data->operation & SET_IGC) {
+    if (SetIGC(meta_data->igc, &layer_buffer.igc) != kErrorNone) {
+      return kErrorNotSupported;
+    }
+  }
+
+  if (meta_data->operation & UPDATE_REFRESH_RATE) {
+    layer->frame_rate = RoundToStandardFPS(meta_data->refreshrate);
+  }
+
+  if ((meta_data->operation & PP_PARAM_INTERLACED) && meta_data->interlaced) {
+    layer_buffer.flags.interlace = true;
+  }
+
+  if (meta_data->operation & LINEAR_FORMAT) {
+    layer_buffer.format = GetSDMFormat(INT32(meta_data->linearFormat), 0);
+  }
+
+  if (meta_data->operation & SET_SINGLE_BUFFER_MODE) {
+    layer->flags.single_buffer = meta_data->isSingleBufferMode;
+    // Graphics can set this operation on all types of layers including FB and set the actual value
+    // to 0. To protect against SET operations of 0 value, we need to do a logical OR.
+    layer_stack_.flags.single_buffered_layer_present |= meta_data->isSingleBufferMode;
+  }
+
+  if (meta_data->operation & S3D_FORMAT) {
+    std::map<int, LayerBufferS3DFormat>::iterator it =
+        s3d_format_hwc_to_sdm_.find(INT32(meta_data->s3dFormat));
+    if (it != s3d_format_hwc_to_sdm_.end()) {
+      layer->input_buffer.s3d_format = it->second;
+    } else {
+      DLOGW("Invalid S3D format %d", meta_data->s3dFormat);
+    }
+  }
+
+  return kErrorNone;
+}
+
+int HWCDisplay::SetPanelBrightness(int level) {
+  int ret = 0;
+  if (display_intf_)
+    ret = display_intf_->SetPanelBrightness(level);
+  else
+    ret = -EINVAL;
+
+  return ret;
+}
+
+int HWCDisplay::GetPanelBrightness(int *level) {
+  return display_intf_->GetPanelBrightness(level);
+}
+
+int HWCDisplay::CachePanelBrightness(int level) {
+  int ret = 0;
+  if (display_intf_)
+    ret = display_intf_->CachePanelBrightness(level);
+  else
+    ret = -EINVAL;
+
+  return ret;
+}
+
+int HWCDisplay::ToggleScreenUpdates(bool enable) {
+  const hwc_procs_t *hwc_procs = *hwc_procs_;
+  display_paused_ = enable ? false : true;
+  hwc_procs->invalidate(hwc_procs);
+  return 0;
+}
+
+int HWCDisplay::ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+                                     PPDisplayAPIPayload *out_payload,
+                                     PPPendingParams *pending_action) {
+  int ret = 0;
+
+  if (display_intf_)
+    ret = display_intf_->ColorSVCRequestRoute(in_payload, out_payload, pending_action);
+  else
+    ret = -EINVAL;
+
+  return ret;
+}
+
+int HWCDisplay::GetVisibleDisplayRect(hwc_rect_t* visible_rect) {
+  if (!IsValid(display_rect_)) {
+    return -EINVAL;
+  }
+
+  visible_rect->left = INT(display_rect_.left);
+  visible_rect->top = INT(display_rect_.top);
+  visible_rect->right = INT(display_rect_.right);
+  visible_rect->bottom = INT(display_rect_.bottom);
+  DLOGI("Dpy = %d Visible Display Rect(%d %d %d %d)", visible_rect->left, visible_rect->top,
+        visible_rect->right, visible_rect->bottom);
+
+  return 0;
+}
+
+void HWCDisplay::SetSecureDisplay(bool secure_display_active, bool force_flush) {
+  secure_display_active_ = secure_display_active;
+  return;
+}
+
+int HWCDisplay::SetActiveDisplayConfig(int config) {
+  return display_intf_->SetActiveConfig(UINT32(config)) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetActiveDisplayConfig(uint32_t *config) {
+  return display_intf_->GetActiveConfig(config) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetDisplayConfigCount(uint32_t *count) {
+  return display_intf_->GetNumVariableInfoConfigs(count) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetDisplayAttributesForConfig(int config,
+                                            DisplayConfigVariableInfo *display_attributes) {
+  return display_intf_->GetConfig(UINT32(config), display_attributes) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetDisplayFixedConfig(DisplayConfigFixedInfo *fixed_info) {
+  return display_intf_->GetConfig(fixed_info) == kErrorNone ? 0 : -1;
+}
+
+// TODO(user): HWC needs to know updating for dyn_fps, cpu hint features,
+// once the features are moved to SDM, the two functions below can be removed.
+uint32_t HWCDisplay::GetUpdatingLayersCount(uint32_t app_layer_count) {
+  uint32_t updating_count = 0;
+
+  for (uint i = 0; i < app_layer_count; i++) {
+    Layer *layer = layer_stack_.layers.at(i);
+    if (layer->flags.updating) {
+      updating_count++;
+    }
+  }
+
+  return updating_count;
+}
+
+bool HWCDisplay::SingleVideoLayerUpdating(uint32_t app_layer_count) {
+  uint32_t updating_count = 0;
+
+  for (uint i = 0; i < app_layer_count; i++) {
+    Layer *layer = layer_stack_.layers[i];
+    // TODO(user): disable DRC feature in S3D playbacl case.S3D video
+    // need play in dedicate resolution and fps, if DRC switch the
+    // mode to an non S3D supported mode, it would break S3D playback.
+    // Need figure out a way to make S3D and DRC co-exist.
+    if (layer->flags.updating && (layer->input_buffer.flags.video == true) &&
+       (layer->input_buffer.s3d_format == kS3dFormatNone)) {
+      updating_count++;
+    }
+  }
+
+  return (updating_count == 1);
+}
+
+uint32_t HWCDisplay::RoundToStandardFPS(float fps) {
+  static const uint32_t standard_fps[4] = {30, 24, 48, 60};
+  uint32_t frame_rate = (uint32_t)(fps);
+
+  int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
+  for (int i = 0; i < count; i++) {
+    if ((standard_fps[i] - frame_rate) < 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 frame_rate;
+}
+
+uint32_t HWCDisplay::SanitizeRefreshRate(uint32_t req_refresh_rate) {
+  uint32_t refresh_rate = req_refresh_rate;
+
+  if (refresh_rate < min_refresh_rate_) {
+    // Pick the next multiple of request which is within the range
+    refresh_rate = (((min_refresh_rate_ / refresh_rate) +
+                     ((min_refresh_rate_ % refresh_rate) ? 1 : 0)) * refresh_rate);
+  }
+
+  if (refresh_rate > max_refresh_rate_) {
+    refresh_rate = max_refresh_rate_;
+  }
+
+  return refresh_rate;
+}
+
+DisplayClass HWCDisplay::GetDisplayClass() {
+  return display_class_;
+}
+
+void HWCDisplay::PrepareDynamicRefreshRate(Layer *layer) {
+  if (layer->frame_rate > metadata_refresh_rate_) {
+    metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
+  } else {
+    layer->frame_rate = current_refresh_rate_;
+  }
+}
+
+bool HWCDisplay::IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions) {
+  // based on dirty_regions determine if its updating
+  // dirty_rect count = 0 - whole layer - updating.
+  // dirty_rect count = 1 or more valid rects - updating.
+  // dirty_rect count = 1 with (0,0,0,0) - not updating.
+  return (dirty_regions.empty() || IsValid(dirty_regions.at(0)));
+}
+
+int HWCDisplay::GetDisplayPort(DisplayPort *port) {
+  return display_intf_->GetDisplayPort(port) == kErrorNone ? 0 : -1;
+}
+
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc/hwc_display.h b/sdm845/sdm/libs/hwc/hwc_display.h
new file mode 100644
index 0000000..b0a40d5
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_display.h
@@ -0,0 +1,266 @@
+/*
+* Copyright (c) 2014 - 2017, 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>
+#include <qdMetaData.h>
+#include <QService.h>
+#include <private/color_params.h>
+#include <map>
+#include <vector>
+#include <string>
+
+namespace sdm {
+
+class BlitEngine;
+class HWCToneMapper;
+
+// Subclasses set this to their type. This has to be different from DisplayType.
+// This is to avoid RTTI and dynamic_cast
+enum DisplayClass {
+  DISPLAY_CLASS_PRIMARY,
+  DISPLAY_CLASS_EXTERNAL,
+  DISPLAY_CLASS_VIRTUAL,
+  DISPLAY_CLASS_NULL
+};
+
+class HWCColorMode {
+ public:
+  explicit HWCColorMode(DisplayInterface *display_intf) : display_intf_(display_intf) {}
+  ~HWCColorMode() {}
+  void Init();
+  void DeInit() {}
+  int SetColorMode(const std::string &color_mode);
+  const std::vector<std::string> &GetColorModes();
+  int SetColorTransform(uint32_t matrix_count, const float *matrix);
+
+ private:
+  static const uint32_t kColorTransformMatrixCount = 16;
+  template <class T>
+  void CopyColorTransformMatrix(const T *input_matrix, double *output_matrix) {
+    for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
+      output_matrix[i] = static_cast<double>(input_matrix[i]);
+    }
+  }
+  int PopulateColorModes();
+  DisplayInterface *display_intf_ = NULL;
+  std::vector<std::string> color_modes_ = {};
+  std::string current_color_mode_ = {};
+};
+
+class HWCDisplay : public DisplayEventHandler {
+ public:
+  enum {
+    SET_METADATA_DYN_REFRESH_RATE,
+    SET_BINDER_DYN_REFRESH_RATE,
+    SET_DISPLAY_MODE,
+    SET_QDCM_SOLID_FILL_INFO,
+    UNSET_QDCM_SOLID_FILL_INFO,
+  };
+
+  virtual ~HWCDisplay() { }
+  virtual int Init();
+  virtual int Deinit();
+  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);
+
+  // Framebuffer configurations
+  virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs);
+  virtual int GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
+                                   int32_t *values);
+  virtual int GetActiveConfig();
+  virtual int SetActiveConfig(int index);
+
+  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 DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) {
+    return kErrorNotSupported;
+  }
+  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 int SetDisplayStatus(uint32_t display_status);
+  virtual int OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
+  virtual int Perform(uint32_t operation, ...);
+  virtual int SetCursorPosition(int x, int y);
+  virtual void SetSecureDisplay(bool secure_display_active, bool force_flush);
+  virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height);
+  virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+  virtual void GetPanelResolution(uint32_t *width, uint32_t *height);
+
+  // Captures frame output in the buffer specified by output_buffer_info. The API is
+  // non-blocking and the client is expected to check operation status later on.
+  // Returns -1 if the input is invalid.
+  virtual int FrameCaptureAsync(const BufferInfo& output_buffer_info, bool post_processed) {
+    return -1;
+  }
+  // Returns the status of frame capture operation requested with FrameCaptureAsync().
+  // -EAGAIN : No status obtain yet, call API again after another frame.
+  // < 0 : Operation happened but failed.
+  // 0 : Success.
+  virtual int GetFrameCaptureStatus() { return -EAGAIN; }
+
+  virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data) {
+    return kErrorNotSupported;
+  }
+
+  // Display Configurations
+  virtual int SetActiveDisplayConfig(int config);
+  virtual int GetActiveDisplayConfig(uint32_t *config);
+  virtual int GetDisplayConfigCount(uint32_t *count);
+  virtual int GetDisplayAttributesForConfig(int config,
+                                            DisplayConfigVariableInfo *display_attributes);
+  virtual int GetDisplayFixedConfig(DisplayConfigFixedInfo *fixed_info);
+
+  int SetPanelBrightness(int level);
+  int GetPanelBrightness(int *level);
+  int CachePanelBrightness(int level);
+  int ToggleScreenUpdates(bool enable);
+  int ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+                           PPDisplayAPIPayload *out_payload,
+                           PPPendingParams *pending_action);
+  int GetVisibleDisplayRect(hwc_rect_t* rect);
+  DisplayClass GetDisplayClass();
+  int GetDisplayPort(DisplayPort *port);
+
+ protected:
+  enum DisplayStatus {
+    kDisplayStatusOffline = 0,
+    kDisplayStatusOnline,
+    kDisplayStatusPause,
+    kDisplayStatusResume,
+  };
+
+  // Dim layer flag set by SurfaceFlinger service.
+  static const uint32_t kDimLayer = 0x80000000;
+
+  // Maximum number of layers supported by display manager.
+  static const uint32_t kMaxLayerCount = 32;
+
+  HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type, int id,
+             bool needs_blit, qService::QService *qservice, DisplayClass display_class);
+
+  // DisplayEventHandler methods
+  virtual DisplayError VSync(const DisplayEventVSync &vsync);
+  virtual DisplayError Refresh();
+  virtual DisplayError CECMessage(char *message);
+
+  int AllocateLayerStack(hwc_display_contents_1_t *content_list);
+  void FreeLayerStack();
+  virtual int PrePrepareLayerStack(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);
+  virtual void DumpOutputBuffer(const BufferInfo& buffer_info, void *base, int fence);
+  virtual uint32_t RoundToStandardFPS(float fps);
+  virtual uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
+  virtual void PrepareDynamicRefreshRate(Layer *layer);
+  virtual DisplayError DisablePartialUpdateOneFrame() {
+    return kErrorNotSupported;
+  }
+  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 LayerComposition &source, int32_t *target);
+  inline void SetBlending(const int32_t &source, LayerBlending *target);
+  int SetFormat(const int32_t &source, const int flags, LayerBufferFormat *target);
+  void SetLayerS3DMode(const LayerBufferS3DFormat &source, uint32_t *target);
+  LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
+  const char *GetDisplayString();
+  void MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list);
+  virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
+  DisplayError SetCSC(const MetaData_t *meta_data, ColorMetaData *color_metadata);
+  DisplayError SetIGC(IGC_t source, LayerIGC *target);
+  DisplayError SetMetaData(const private_handle_t *pvt_handle, Layer *layer);
+  bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list);
+  bool IsLayerUpdating(hwc_display_contents_1_t *content_list, const Layer *layer);
+  bool IsNonIntegralSourceCrop(const hwc_frect_t &source);
+  uint32_t GetUpdatingLayersCount(uint32_t app_layer_count);
+  bool SingleVideoLayerUpdating(uint32_t app_layer_count);
+  bool IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions);
+
+  enum {
+    INPUT_LAYER_DUMP,
+    OUTPUT_LAYER_DUMP,
+  };
+
+  CoreInterface *core_intf_;
+  hwc_procs_t const **hwc_procs_;
+  DisplayType type_;
+  int id_;
+  bool needs_blit_ = false;
+  DisplayInterface *display_intf_ = NULL;
+  LayerStack layer_stack_;
+  bool flush_on_error_ = false;
+  bool flush_ = false;
+  uint32_t dump_frame_count_ = 0;
+  uint32_t dump_frame_index_ = 0;
+  bool dump_input_layers_ = false;
+  uint32_t last_power_mode_;
+  bool swap_interval_zero_ = false;
+  bool display_paused_ = false;
+  uint32_t min_refresh_rate_ = 0;
+  uint32_t max_refresh_rate_ = 0;
+  uint32_t current_refresh_rate_ = 0;
+  bool use_metadata_refresh_rate_ = false;
+  uint32_t metadata_refresh_rate_ = 0;
+  uint32_t force_refresh_rate_ = 0;
+  bool boot_animation_completed_ = false;
+  bool shutdown_pending_ = false;
+  bool use_blit_comp_ = false;
+  bool secure_display_active_ = false;
+  uint32_t skip_prepare_cnt = 0;
+  bool solid_fill_enable_ = false;
+  bool disable_animation_ = false;
+  uint32_t solid_fill_color_ = 0;
+  LayerRect display_rect_;
+  std::map<int, LayerBufferS3DFormat> s3d_format_hwc_to_sdm_;
+  bool animating_ = false;
+  HWCToneMapper *tone_mapper_ = NULL;
+  HWCColorMode *color_mode_ = NULL;
+  int disable_hdr_handling_ = 0;  // disables HDR handling.
+
+ private:
+  void DumpInputBuffers(hwc_display_contents_1_t *content_list);
+  int PrepareLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer);
+  void CommitLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer);
+  BlitEngine *blit_engine_ = NULL;
+  qService::QService *qservice_ = NULL;
+  DisplayClass display_class_;
+};
+
+inline int HWCDisplay::Perform(uint32_t operation, ...) {
+  return 0;
+}
+
+}  // namespace sdm
+
+#endif  // __HWC_DISPLAY_H__
+
diff --git a/sdm845/sdm/libs/hwc/hwc_display_external.cpp b/sdm845/sdm/libs/hwc/hwc_display_external.cpp
new file mode 100644
index 0000000..da216f7
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_display_external.cpp
@@ -0,0 +1,335 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cutils/properties.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <algorithm>
+
+#include "hwc_display_external.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayExternal"
+
+namespace sdm {
+
+int HWCDisplayExternal::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                               qService::QService *qservice, HWCDisplay **hwc_display) {
+  return Create(core_intf, hwc_procs, 0, 0, qservice, false, hwc_display);
+}
+
+int HWCDisplayExternal::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                               uint32_t primary_width, uint32_t primary_height,
+                               qService::QService *qservice, bool use_primary_res,
+                               HWCDisplay **hwc_display) {
+  uint32_t external_width = 0;
+  uint32_t external_height = 0;
+  int drc_enabled = 0;
+  int drc_reset_fps_enabled = 0;
+  DisplayError error = kErrorNone;
+
+  HWCDisplay *hwc_display_external = new HWCDisplayExternal(core_intf, hwc_procs, qservice);
+  int status = hwc_display_external->Init();
+  if (status) {
+    delete hwc_display_external;
+    return status;
+  }
+
+  error = hwc_display_external->GetMixerResolution(&external_width, &external_height);
+  if (error != kErrorNone) {
+    return -EINVAL;
+  }
+
+  if (primary_width && primary_height) {
+    // use_primary_res means HWCDisplayExternal should directly set framebuffer resolution to the
+    // provided primary_width and primary_height
+    if (use_primary_res) {
+      external_width = primary_width;
+      external_height = primary_height;
+    } else {
+      int downscale_enabled = 0;
+      HWCDebugHandler::Get()->GetProperty("sdm.debug.downscale_external", &downscale_enabled);
+      if (downscale_enabled) {
+        GetDownscaleResolution(primary_width, primary_height, &external_width, &external_height);
+      }
+    }
+  }
+
+  status = hwc_display_external->SetFrameBufferResolution(external_width, external_height);
+  if (status) {
+    Destroy(hwc_display_external);
+    return status;
+  }
+
+  HWCDebugHandler::Get()->GetProperty("sdm.hdmi.drc_enabled", &(drc_enabled));
+  reinterpret_cast<HWCDisplayExternal *>(hwc_display_external)->drc_enabled_ = drc_enabled;
+
+  HWCDebugHandler::Get()->GetProperty("sdm.hdmi.drc_reset_fps", &(drc_reset_fps_enabled));
+  reinterpret_cast<HWCDisplayExternal *>(hwc_display_external)->drc_reset_fps_enabled_ =
+                                                                drc_reset_fps_enabled;
+
+  *hwc_display = hwc_display_external;
+
+  return status;
+}
+
+void HWCDisplayExternal::Destroy(HWCDisplay *hwc_display) {
+  hwc_display->Deinit();
+  delete hwc_display;
+}
+
+HWCDisplayExternal::HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                                       qService::QService *qservice)
+  : HWCDisplay(core_intf, hwc_procs, kHDMI, HWC_DISPLAY_EXTERNAL, false, qservice,
+               DISPLAY_CLASS_EXTERNAL) {
+}
+
+int HWCDisplayExternal::Prepare(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+  DisplayError error = kErrorNone;
+
+  if (secure_display_active_) {
+    MarkLayersForGPUBypass(content_list);
+    return status;
+  }
+
+  status = AllocateLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  status = PrePrepareLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  if (content_list->numHwLayers <= 1) {
+    flush_ = true;
+    return 0;
+  }
+
+  bool one_video_updating_layer = SingleVideoLayerUpdating(UINT32(content_list->numHwLayers - 1));
+
+  uint32_t refresh_rate = GetOptimalRefreshRate(one_video_updating_layer);
+  bool final_rate = force_refresh_rate_ ? true : false;
+  error = display_intf_->SetRefreshRate(refresh_rate, final_rate);
+  if (error == kErrorNone) {
+    // On success, set current refresh rate to new refresh rate
+    current_refresh_rate_ = refresh_rate;
+  }
+
+  status = PrepareLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  return 0;
+}
+
+int HWCDisplayExternal::Commit(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  if (secure_display_active_) {
+    return status;
+  }
+
+  status = HWCDisplay::CommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  status = HWCDisplay::PostCommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  return 0;
+}
+
+void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+  if (display_intf_->IsUnderscanSupported()) {
+    return;
+  }
+
+  // Read user defined width and height ratio
+  int width = 0, height = 0;
+  HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_width", &width);
+  float width_ratio = FLOAT(width) / 100.0f;
+  HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_height", &height);
+  float height_ratio = FLOAT(height) / 100.0f;
+
+  if (width_ratio == 0.0f ||  height_ratio == 0.0f) {
+    return;
+  }
+
+  uint32_t mixer_width = 0;
+  uint32_t mixer_height = 0;
+  GetMixerResolution(&mixer_width, &mixer_height);
+
+  if (mixer_width == 0 || mixer_height == 0) {
+    DLOGV("Invalid mixer dimensions (%d, %d)", mixer_width, mixer_height);
+    return;
+  }
+
+  uint32_t new_mixer_width = UINT32(mixer_width * FLOAT(1.0f - width_ratio));
+  uint32_t new_mixer_height = UINT32(mixer_height * FLOAT(1.0f - height_ratio));
+
+  int x_offset = INT((FLOAT(mixer_width) * width_ratio) / 2.0f);
+  int y_offset = INT((FLOAT(mixer_height) * height_ratio) / 2.0f);
+
+  display_frame->left = (display_frame->left * INT32(new_mixer_width) / INT32(mixer_width))
+                        + x_offset;
+  display_frame->top = (display_frame->top * INT32(new_mixer_height) / INT32(mixer_height)) +
+                       y_offset;
+  display_frame->right = ((display_frame->right * INT32(new_mixer_width)) / INT32(mixer_width)) +
+                         x_offset;
+  display_frame->bottom = ((display_frame->bottom * INT32(new_mixer_height)) / INT32(mixer_height))
+                          + y_offset;
+}
+
+void HWCDisplayExternal::SetSecureDisplay(bool secure_display_active, bool force_flush) {
+  if (secure_display_active_ != secure_display_active) {
+    secure_display_active_ = secure_display_active;
+
+    if (secure_display_active_) {
+      DisplayError error = display_intf_->Flush();
+      if (error != kErrorNone) {
+        DLOGE("Flush failed. Error = %d", error);
+      }
+    }
+  }
+  return;
+}
+
+static void 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;
+}
+
+void HWCDisplayExternal::GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
+                                        uint32_t *non_primary_width, uint32_t *non_primary_height) {
+  uint32_t primary_area = primary_width * primary_height;
+  uint32_t non_primary_area = (*non_primary_width) * (*non_primary_height);
+
+  if (primary_area > non_primary_area) {
+    if (primary_height > primary_width) {
+      std::swap(primary_height, primary_width);
+    }
+    AdjustSourceResolution(primary_width, primary_height, non_primary_width, non_primary_height);
+  }
+}
+
+uint32_t HWCDisplayExternal::RoundToStandardFPS(float fps) {
+  static const uint32_t standard_fps[] = {23976, 24000, 25000, 29970, 30000, 50000, 59940, 60000};
+  static const uint32_t mapping_fps[] = {59940, 60000, 60000, 59940, 60000, 50000, 59940, 60000};
+  uint32_t frame_rate = (uint32_t)(fps * 1000);
+
+  // process non valid
+  if (frame_rate == 0) {
+    return current_refresh_rate_;
+  }
+
+  int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
+  for (int i = 0; i < count; i++) {
+    // Most likely used for video, the fps for frames should be stable from video side.
+    if (standard_fps[i] > frame_rate) {
+      if (i > 0) {
+        if ((standard_fps[i] - frame_rate) > (frame_rate - standard_fps[i-1])) {
+          return mapping_fps[i-1];
+        } else {
+          return mapping_fps[i];
+        }
+      } else {
+        return mapping_fps[i];
+      }
+    }
+  }
+
+  return standard_fps[count - 1];
+}
+
+void HWCDisplayExternal::PrepareDynamicRefreshRate(Layer *layer) {
+  if (layer->input_buffer.flags.video) {
+    if (layer->frame_rate != 0) {
+      metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
+    } else {
+      metadata_refresh_rate_ = current_refresh_rate_;
+    }
+    layer->frame_rate = current_refresh_rate_;
+  } else if (!layer->frame_rate) {
+    layer->frame_rate = current_refresh_rate_;
+  }
+}
+
+void HWCDisplayExternal::ForceRefreshRate(uint32_t refresh_rate) {
+  if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
+       force_refresh_rate_ == refresh_rate) {
+    // Cannot honor force refresh rate, as its beyond the range or new request is same
+    return;
+  }
+
+  force_refresh_rate_ = refresh_rate;
+}
+
+uint32_t HWCDisplayExternal::GetOptimalRefreshRate(bool one_updating_layer) {
+  if (force_refresh_rate_) {
+    return force_refresh_rate_;
+  } else if (one_updating_layer && drc_enabled_) {
+    return metadata_refresh_rate_;
+  }
+
+  if (drc_reset_fps_enabled_) {
+    DisplayConfigVariableInfo fb_config;
+    display_intf_->GetFrameBufferConfig(&fb_config);
+    return (fb_config.fps * 1000);
+  }
+
+  return current_refresh_rate_;
+}
+
+int HWCDisplayExternal::Perform(uint32_t operation, ...) {
+  va_list args;
+  va_start(args, operation);
+  int val = va_arg(args, int32_t);
+  va_end(args);
+  switch (operation) {
+    case SET_BINDER_DYN_REFRESH_RATE:
+      ForceRefreshRate(UINT32(val));
+      break;
+    default:
+      DLOGW("Invalid operation %d", operation);
+      return -EINVAL;
+  }
+
+  return 0;
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/hwc/hwc_display_external.h b/sdm845/sdm/libs/hwc/hwc_display_external.h
new file mode 100644
index 0000000..c5ac3d7
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_display_external.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_DISPLAY_EXTERNAL_H__
+#define __HWC_DISPLAY_EXTERNAL_H__
+
+#include "hwc_display.h"
+
+namespace sdm {
+
+class HWCDisplayExternal : public HWCDisplay {
+ public:
+  static int Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, uint32_t primary_width,
+                    uint32_t primary_height, qService::QService *qservice, bool use_primary_res,
+                    HWCDisplay **hwc_display);
+  static int Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                    qService::QService *qservice, HWCDisplay **hwc_display);
+  static void Destroy(HWCDisplay *hwc_display);
+  virtual int Prepare(hwc_display_contents_1_t *content_list);
+  virtual int Commit(hwc_display_contents_1_t *content_list);
+  virtual void SetSecureDisplay(bool secure_display_active, bool force_flush);
+  virtual int Perform(uint32_t operation, ...);
+
+ protected:
+  virtual uint32_t RoundToStandardFPS(float fps);
+  virtual void PrepareDynamicRefreshRate(Layer *layer);
+  int drc_enabled_ = 0;
+  int drc_reset_fps_enabled_ = 0;
+
+ private:
+  HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                     qService::QService *qservice);
+  void ApplyScanAdjustment(hwc_rect_t *display_frame);
+  static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
+                                     uint32_t *virtual_width, uint32_t *virtual_height);
+  void ForceRefreshRate(uint32_t refresh_rate);
+  uint32_t GetOptimalRefreshRate(bool one_updating_layer);
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_DISPLAY_EXTERNAL_H__
+
diff --git a/sdm845/sdm/libs/hwc/hwc_display_external_test.cpp b/sdm845/sdm/libs/hwc/hwc_display_external_test.cpp
new file mode 100644
index 0000000..e629cd6
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_display_external_test.cpp
@@ -0,0 +1,764 @@
+/*
+* Copyright (c) 2017, 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 <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/formats.h>
+#include <algorithm>
+#include <array>
+#include <sstream>
+#include <string>
+#include <fstream>
+
+#include "hwc_display_external_test.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayExternalTest"
+
+namespace sdm {
+
+using std::array;
+
+int HWCDisplayExternalTest::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                                   qService::QService *qservice, uint32_t panel_bpp,
+                                   uint32_t pattern_type, HWCDisplay **hwc_display) {
+  HWCDisplay *hwc_external_test = new HWCDisplayExternalTest(core_intf, hwc_procs, qservice,
+                                                             panel_bpp, pattern_type);
+
+  int status = static_cast<HWCDisplayExternalTest *>(hwc_external_test)->Init();
+  if (status) {
+    delete hwc_external_test;
+    return status;
+  }
+
+  *hwc_display = hwc_external_test;
+
+  DLOGI("panel_bpp %d, pattern_type %d", panel_bpp, pattern_type);
+
+  return status;
+}
+
+void HWCDisplayExternalTest::Destroy(HWCDisplay *hwc_display) {
+  static_cast<HWCDisplayExternalTest *>(hwc_display)->Deinit();
+
+  delete hwc_display;
+}
+
+HWCDisplayExternalTest::HWCDisplayExternalTest(CoreInterface *core_intf,
+                                               hwc_procs_t const **hwc_procs,
+                                               qService::QService *qservice, uint32_t panel_bpp,
+                                               uint32_t pattern_type)
+  : HWCDisplay(core_intf, hwc_procs, kHDMI, HWC_DISPLAY_EXTERNAL, false, qservice,
+               DISPLAY_CLASS_EXTERNAL), panel_bpp_(panel_bpp), pattern_type_(pattern_type) {
+}
+
+int HWCDisplayExternalTest::Init() {
+  uint32_t external_width = 0;
+  uint32_t external_height = 0;
+
+  int status = HWCDisplay::Init();
+  if (status) {
+    return status;
+  }
+
+  buffer_allocator_ = new HWCBufferAllocator();
+
+  status = CreateLayerStack();
+  if (status) {
+    Deinit();
+    return status;
+  }
+
+  DisplayError error = HWCDisplay::GetMixerResolution(&external_width, &external_height);
+  if (error != kErrorNone) {
+    Deinit();
+    return -EINVAL;
+  }
+
+  status = HWCDisplay::SetFrameBufferResolution(external_width, external_height);
+  if (status) {
+    Deinit();
+    return status;
+  }
+
+  return status;
+}
+
+int HWCDisplayExternalTest::Deinit() {
+  DestroyLayerStack();
+
+  delete buffer_allocator_;
+  buffer_allocator_ = NULL;
+
+  return HWCDisplay::Deinit();
+}
+
+
+int HWCDisplayExternalTest::Prepare(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  if (secure_display_active_) {
+    MarkLayersForGPUBypass(content_list);
+    return status;
+  }
+
+  if (!content_list || !content_list->numHwLayers) {
+    DLOGW("Invalid content list");
+    return -EINVAL;
+  }
+
+  if (shutdown_pending_) {
+    return 0;
+  }
+
+  DisplayError error = display_intf_->Prepare(&layer_stack_);
+  if (error != kErrorNone) {
+    if (error == kErrorShutDown) {
+      shutdown_pending_ = true;
+    } else if (error != kErrorPermission) {
+      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;
+    }
+  }
+
+  MarkLayersForGPUBypass(content_list);
+
+  return 0;
+}
+
+int HWCDisplayExternalTest::Commit(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  if (secure_display_active_) {
+    return status;
+  }
+
+  if (!content_list || !content_list->numHwLayers) {
+    DLOGW("Invalid content list");
+    return -EINVAL;
+  }
+
+  if (shutdown_pending_) {
+    return 0;
+  }
+
+  DumpInputBuffer();
+
+  if (!flush_) {
+    DisplayError error = kErrorUndefined;
+
+    error = display_intf_->Commit(&layer_stack_);
+    if (error == kErrorNone) {
+      // A commit is successfully submitted, start flushing on failure now onwards.
+      flush_on_error_ = true;
+    } else {
+      if (error == kErrorShutDown) {
+        shutdown_pending_ = true;
+        return status;
+      } else if (error != kErrorPermission) {
+        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 PostCommit(content_list);
+}
+
+void HWCDisplayExternalTest::SetSecureDisplay(bool secure_display_active, bool force_flush) {
+  if (secure_display_active_ != secure_display_active) {
+    secure_display_active_ = secure_display_active;
+
+    if (secure_display_active_) {
+      DisplayError error = display_intf_->Flush();
+      if (error != kErrorNone) {
+        DLOGE("Flush failed. Error = %d", error);
+      }
+    }
+  }
+  return;
+}
+
+int HWCDisplayExternalTest::Perform(uint32_t operation, ...) {
+  return 0;
+}
+
+void HWCDisplayExternalTest::DumpInputBuffer() {
+  if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
+    return;
+  }
+
+  const char *dir_path = "/data/misc/display/frame_dump_external";
+  uint32_t width = buffer_info_.alloc_buffer_info.aligned_width;
+  uint32_t height = buffer_info_.alloc_buffer_info.aligned_height;
+  string format_str = GetFormatString(buffer_info_.buffer_config.format);
+
+  char *buffer = reinterpret_cast<char *>(mmap(NULL, buffer_info_.alloc_buffer_info.size,
+                                                PROT_READ|PROT_WRITE, MAP_SHARED,
+                                                buffer_info_.alloc_buffer_info.fd, 0));
+  if (buffer == MAP_FAILED) {
+    DLOGW("mmap failed. err = %d", errno);
+    return;
+  }
+
+  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;
+  }
+
+  if (buffer) {
+    std::stringstream dump_file_name;
+    dump_file_name << dir_path;
+    dump_file_name << "/input_layer_" << width << "x" << height << "_" << format_str << ".raw";
+
+    std::fstream fs;
+    fs.open(dump_file_name.str().c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
+    if (!fs.is_open()) {
+      DLOGI("File open failed %s", dump_file_name.str().c_str());
+      return;
+    }
+
+    fs.write(buffer, (std::streamsize)buffer_info_.alloc_buffer_info.size);
+    fs.close();
+
+    DLOGI("Frame Dump %s: is successful", dump_file_name.str().c_str());
+  }
+
+  // Dump only once as the content is going to be same for all draw cycles
+  if (dump_frame_count_) {
+    dump_frame_count_ = 0;
+  }
+
+  if (munmap(buffer, buffer_info_.alloc_buffer_info.size) != 0) {
+    DLOGW("munmap failed. err = %d", errno);
+    return;
+  }
+}
+
+void HWCDisplayExternalTest::CalcCRC(uint32_t color_val, std::bitset<16> *crc_data) {
+  std::bitset<16> color = {};
+  std::bitset<16> temp_crc = {};
+
+  switch (panel_bpp_) {
+    case kDisplayBpp18:
+      color = (color_val & 0xFC) << 8;
+      break;
+    case kDisplayBpp24:
+      color = color_val << 8;
+      break;
+    case kDisplayBpp30:
+      color = color_val << 6;
+      break;
+    default:
+      return;
+  }
+
+  temp_crc[15] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^
+                 (*crc_data)[4] ^ (*crc_data)[5] ^ (*crc_data)[6] ^ (*crc_data)[7] ^
+                 (*crc_data)[8] ^ (*crc_data)[9] ^ (*crc_data)[10] ^ (*crc_data)[11] ^
+                 (*crc_data)[12] ^ (*crc_data)[14] ^ (*crc_data)[15] ^ color[0] ^ color[1] ^
+                 color[2] ^ color[3] ^ color[4] ^ color[5] ^ color[6] ^ color[7] ^ color[8] ^
+                 color[9] ^ color[10] ^ color[11] ^ color[12] ^ color[14] ^ color[15];
+
+  temp_crc[14] = (*crc_data)[12] ^ (*crc_data)[13] ^ color[12] ^ color[13];
+  temp_crc[13] = (*crc_data)[11] ^ (*crc_data)[12] ^ color[11] ^ color[12];
+  temp_crc[12] = (*crc_data)[10] ^ (*crc_data)[11] ^ color[10] ^ color[11];
+  temp_crc[11] = (*crc_data)[9] ^ (*crc_data)[10] ^ color[9] ^ color[10];
+  temp_crc[10] = (*crc_data)[8] ^ (*crc_data)[9] ^ color[8] ^ color[9];
+  temp_crc[9] = (*crc_data)[7] ^ (*crc_data)[8] ^ color[7] ^ color[8];
+  temp_crc[8] = (*crc_data)[6] ^ (*crc_data)[7] ^ color[6] ^ color[7];
+  temp_crc[7] = (*crc_data)[5] ^ (*crc_data)[6] ^ color[5] ^ color[6];
+  temp_crc[6] = (*crc_data)[4] ^ (*crc_data)[5] ^ color[4] ^ color[5];
+  temp_crc[5] = (*crc_data)[3] ^ (*crc_data)[4] ^ color[3] ^ color[4];
+  temp_crc[4] = (*crc_data)[2] ^ (*crc_data)[3] ^ color[2] ^ color[3];
+  temp_crc[3] = (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[15] ^ color[1] ^ color[2] ^ color[15];
+  temp_crc[2] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[14] ^ color[0] ^ color[1] ^ color[14];
+
+  temp_crc[1] = (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^ (*crc_data)[4] ^ (*crc_data)[5] ^
+                (*crc_data)[6] ^ (*crc_data)[7] ^ (*crc_data)[8] ^ (*crc_data)[9] ^
+                (*crc_data)[10] ^ (*crc_data)[11] ^ (*crc_data)[12] ^ (*crc_data)[13] ^
+                (*crc_data)[14] ^ color[1] ^ color[2] ^ color[3] ^ color[4] ^ color[5] ^ color[6] ^
+                color[7] ^ color[8] ^ color[9] ^ color[10] ^ color[11] ^ color[12] ^ color[13] ^
+                color[14];
+
+  temp_crc[0] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^ (*crc_data)[4] ^
+                (*crc_data)[5] ^ (*crc_data)[6] ^ (*crc_data)[7] ^ (*crc_data)[8] ^ (*crc_data)[9] ^
+                (*crc_data)[10] ^ (*crc_data)[11] ^ (*crc_data)[12] ^ (*crc_data)[13] ^
+                (*crc_data)[15] ^ color[0] ^ color[1] ^ color[2] ^ color[3] ^ color[4] ^ color[5] ^
+                color[6] ^ color[7] ^ color[8] ^ color[9] ^ color[10] ^ color[11] ^ color[12] ^
+                color[13] ^ color[15];
+
+  (*crc_data) = temp_crc;
+}
+
+int HWCDisplayExternalTest::FillBuffer() {
+  uint8_t *buffer = reinterpret_cast<uint8_t *>(mmap(NULL, buffer_info_.alloc_buffer_info.size,
+                                                PROT_READ|PROT_WRITE, MAP_SHARED,
+                                                buffer_info_.alloc_buffer_info.fd, 0));
+  if (buffer == MAP_FAILED) {
+    DLOGE("mmap failed. err = %d", errno);
+    return -EFAULT;
+  }
+
+  switch (pattern_type_) {
+    case kPatternColorRamp:
+      GenerateColorRamp(buffer);
+      break;
+    case kPatternBWVertical:
+      GenerateBWVertical(buffer);
+      break;
+    case kPatternColorSquare:
+      GenerateColorSquare(buffer);
+      break;
+    default:
+      DLOGW("Invalid Pattern type %d", pattern_type_);
+      return -EINVAL;
+  }
+
+  if (munmap(buffer, buffer_info_.alloc_buffer_info.size) != 0) {
+    DLOGE("munmap failed. err = %d", errno);
+    return -EFAULT;
+  }
+
+  return 0;
+}
+
+int HWCDisplayExternalTest::GetStride(LayerBufferFormat format, uint32_t width, uint32_t *stride) {
+  switch (format) {
+  case kFormatRGBA8888:
+  case kFormatRGBA1010102:
+    *stride = width * 4;
+    break;
+  case kFormatRGB888:
+    *stride = width * 3;
+    break;
+  default:
+    DLOGE("Unsupported format type %d", format);
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
+void HWCDisplayExternalTest::PixelCopy(uint32_t red, uint32_t green, uint32_t blue, uint32_t alpha,
+                                       uint8_t **buffer) {
+  LayerBufferFormat format = buffer_info_.buffer_config.format;
+
+  switch (format) {
+    case kFormatRGBA8888:
+      *(*buffer)++ = UINT8(red & 0xFF);
+      *(*buffer)++ = UINT8(green & 0xFF);
+      *(*buffer)++ = UINT8(blue & 0xFF);
+      *(*buffer)++ = UINT8(alpha & 0xFF);
+      break;
+    case kFormatRGB888:
+      *(*buffer)++ = UINT8(red & 0xFF);
+      *(*buffer)++ = UINT8(green & 0xFF);
+      *(*buffer)++ = UINT8(blue & 0xFF);
+      break;
+    case kFormatRGBA1010102:
+      // Lower 8 bits of red
+      *(*buffer)++ = UINT8(red & 0xFF);
+
+      // Upper 2 bits of Red + Lower 6 bits of green
+      *(*buffer)++ = UINT8(((green & 0x3F) << 2) | ((red >> 0x8) & 0x3));
+
+      // Upper 4 bits of green + Lower 4 bits of blue
+      *(*buffer)++ = UINT8(((blue & 0xF) << 4) | ((green >> 6) & 0xF));
+
+      // Upper 6 bits of blue + Lower 2 bits of alpha
+      *(*buffer)++ = UINT8(((alpha & 0x3) << 6) | ((blue >> 4) & 0x3F));
+      break;
+    default:
+      DLOGW("format not supported format = %d", format);
+      break;
+  }
+}
+
+void HWCDisplayExternalTest::GenerateColorRamp(uint8_t *buffer) {
+  uint32_t width = buffer_info_.buffer_config.width;
+  uint32_t height = buffer_info_.buffer_config.height;
+  LayerBufferFormat format = buffer_info_.buffer_config.format;
+  uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
+  uint32_t buffer_stride = 0;
+
+  uint32_t color_ramp = 0;
+  uint32_t start_color_val = 0;
+  uint32_t step_size = 1;
+  uint32_t ramp_width = 0;
+  uint32_t ramp_height = 0;
+  uint32_t shift_by = 0;
+
+  std::bitset<16> crc_red = {};
+  std::bitset<16> crc_green = {};
+  std::bitset<16> crc_blue = {};
+
+  switch (panel_bpp_) {
+    case kDisplayBpp18:
+      ramp_height = 64;
+      ramp_width = 64;
+      shift_by = 2;
+      break;
+    case kDisplayBpp24:
+      ramp_height = 64;
+      ramp_width = 256;
+      break;
+    case kDisplayBpp30:
+      ramp_height = 32;
+      ramp_width = 256;
+      start_color_val = 0x180;
+      break;
+    default:
+      return;
+  }
+
+  GetStride(format, aligned_width, &buffer_stride);
+
+  for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
+    uint32_t color_value = start_color_val;
+    uint8_t *temp = buffer + (loop_height * buffer_stride);
+
+    for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
+      if (color_ramp == kColorRedRamp) {
+        PixelCopy(color_value, 0, 0, 0, &temp);
+        CalcCRC(color_value, &crc_red);
+        CalcCRC(0, &crc_green);
+        CalcCRC(0, &crc_blue);
+      }
+      if (color_ramp == kColorGreenRamp) {
+        PixelCopy(0, color_value, 0, 0, &temp);
+        CalcCRC(0, &crc_red);
+        CalcCRC(color_value, &crc_green);
+        CalcCRC(0, &crc_blue);
+      }
+      if (color_ramp == kColorBlueRamp) {
+        PixelCopy(0, 0, color_value, 0, &temp);
+        CalcCRC(0, &crc_red);
+        CalcCRC(0, &crc_green);
+        CalcCRC(color_value, &crc_blue);
+      }
+      if (color_ramp == kColorWhiteRamp) {
+        PixelCopy(color_value, color_value, color_value, 0, &temp);
+        CalcCRC(color_value, &crc_red);
+        CalcCRC(color_value, &crc_green);
+        CalcCRC(color_value, &crc_blue);
+      }
+
+      color_value = (start_color_val + (((loop_width + 1) % ramp_width) * step_size)) << shift_by;
+    }
+
+    if (panel_bpp_ == kDisplayBpp30 && ((loop_height + 1) % ramp_height) == 0) {
+      if (start_color_val == 0x180) {
+        start_color_val = 0;
+        step_size = 4;
+      } else {
+        start_color_val = 0x180;
+        step_size = 1;
+        color_ramp = (color_ramp + 1) % 4;
+      }
+      continue;
+    }
+
+    if (((loop_height + 1) % ramp_height) == 0) {
+      color_ramp = (color_ramp + 1) % 4;
+    }
+  }
+
+  DLOGI("CRC red %x", crc_red.to_ulong());
+  DLOGI("CRC green %x", crc_green.to_ulong());
+  DLOGI("CRC blue %x", crc_blue.to_ulong());
+}
+
+void HWCDisplayExternalTest::GenerateBWVertical(uint8_t *buffer) {
+  uint32_t width = buffer_info_.buffer_config.width;
+  uint32_t height = buffer_info_.buffer_config.height;
+  LayerBufferFormat format = buffer_info_.buffer_config.format;
+  uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
+  uint32_t buffer_stride = 0;
+  uint32_t bits_per_component = panel_bpp_ / 3;
+  uint32_t max_color_val = (1 << bits_per_component) - 1;
+
+  std::bitset<16> crc_red = {};
+  std::bitset<16> crc_green = {};
+  std::bitset<16> crc_blue = {};
+
+  if (panel_bpp_ == kDisplayBpp18) {
+    max_color_val <<= 2;
+  }
+
+  GetStride(format, aligned_width, &buffer_stride);
+
+  for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
+    uint32_t color = 0;
+    uint8_t *temp = buffer + (loop_height * buffer_stride);
+
+    for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
+      if (color == kColorBlack) {
+        PixelCopy(0, 0, 0, 0, &temp);
+        CalcCRC(0, &crc_red);
+        CalcCRC(0, &crc_green);
+        CalcCRC(0, &crc_blue);
+      }
+      if (color == kColorWhite) {
+        PixelCopy(max_color_val, max_color_val, max_color_val, 0, &temp);
+        CalcCRC(max_color_val, &crc_red);
+        CalcCRC(max_color_val, &crc_green);
+        CalcCRC(max_color_val, &crc_blue);
+      }
+
+      color = (color + 1) % 2;
+    }
+  }
+
+  DLOGI("CRC red %x", crc_red.to_ulong());
+  DLOGI("CRC green %x", crc_green.to_ulong());
+  DLOGI("CRC blue %x", crc_blue.to_ulong());
+}
+
+void HWCDisplayExternalTest::GenerateColorSquare(uint8_t *buffer) {
+  uint32_t width = buffer_info_.buffer_config.width;
+  uint32_t height = buffer_info_.buffer_config.height;
+  LayerBufferFormat format = buffer_info_.buffer_config.format;
+  uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
+  uint32_t buffer_stride = 0;
+  uint32_t max_color_val = 0;
+  uint32_t min_color_val = 0;
+
+  std::bitset<16> crc_red = {};
+  std::bitset<16> crc_green = {};
+  std::bitset<16> crc_blue = {};
+
+  switch (panel_bpp_) {
+    case kDisplayBpp18:
+      max_color_val = 63 << 2;  // CEA Dynamic range for 18bpp 0 - 63
+      min_color_val = 0;
+      break;
+    case kDisplayBpp24:
+      max_color_val = 235;  // CEA Dynamic range for 24bpp 16 - 235
+      min_color_val = 16;
+      break;
+    case kDisplayBpp30:
+      max_color_val = 940;  // CEA Dynamic range for 30bpp 64 - 940
+      min_color_val = 64;
+      break;
+    default:
+      return;
+  }
+
+  array<array<uint32_t, 3>, 8> colors = {{
+    {{max_color_val, max_color_val, max_color_val}},  // White Color
+    {{max_color_val, max_color_val, min_color_val}},  // Yellow Color
+    {{min_color_val, max_color_val, max_color_val}},  // Cyan Color
+    {{min_color_val, max_color_val, min_color_val}},  // Green Color
+    {{max_color_val, min_color_val, max_color_val}},  // Megenta Color
+    {{max_color_val, min_color_val, min_color_val}},  // Red Color
+    {{min_color_val, min_color_val, max_color_val}},  // Blue Color
+    {{min_color_val, min_color_val, min_color_val}},  // Black Color
+  }};
+
+  GetStride(format, aligned_width, &buffer_stride);
+
+  for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
+    uint32_t color = 0;
+    uint8_t *temp = buffer + (loop_height * buffer_stride);
+
+    for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
+      PixelCopy(colors[color][0], colors[color][1], colors[color][2], 0, &temp);
+      CalcCRC(colors[color][0], &crc_red);
+      CalcCRC(colors[color][1], &crc_green);
+      CalcCRC(colors[color][2], &crc_blue);
+
+      if (((loop_width + 1) % 64) == 0) {
+        color = (color + 1) % colors.size();
+      }
+    }
+
+    if (((loop_height + 1) % 64) == 0) {
+      std::reverse(colors.begin(), (colors.end() - 1));
+    }
+  }
+
+  DLOGI("CRC red %x", crc_red.to_ulong());
+  DLOGI("CRC green %x", crc_green.to_ulong());
+  DLOGI("CRC blue %x", crc_blue.to_ulong());
+}
+
+int HWCDisplayExternalTest::InitLayer(Layer *layer) {
+  uint32_t active_config = 0;
+  DisplayConfigVariableInfo var_info = {};
+
+  GetActiveDisplayConfig(&active_config);
+
+  GetDisplayAttributesForConfig(INT32(active_config), &var_info);
+
+  layer->flags.updating = 1;
+  layer->src_rect = LayerRect(0, 0, var_info.x_pixels, var_info.y_pixels);
+  layer->dst_rect = layer->src_rect;
+  layer->frame_rate = var_info.fps;
+  layer->blending = kBlendingPremultiplied;
+
+  layer->input_buffer.unaligned_width = var_info.x_pixels;
+  layer->input_buffer.unaligned_height = var_info.y_pixels;
+  buffer_info_.buffer_config.format = kFormatRGBA8888;
+
+  if (layer->composition != kCompositionGPUTarget) {
+    buffer_info_.buffer_config.width = var_info.x_pixels;
+    buffer_info_.buffer_config.height = var_info.y_pixels;
+    switch (panel_bpp_) {
+      case kDisplayBpp18:
+      case kDisplayBpp24:
+        buffer_info_.buffer_config.format = kFormatRGB888;
+        break;
+      case kDisplayBpp30:
+        buffer_info_.buffer_config.format = kFormatRGBA1010102;
+        break;
+      default:
+        DLOGW("panel bpp not supported %d", panel_bpp_);
+        return -EINVAL;
+    }
+    buffer_info_.buffer_config.buffer_count = 1;
+
+    int ret = buffer_allocator_->AllocateBuffer(&buffer_info_);
+    if (ret != 0) {
+      DLOGE("Buffer allocation failed. ret: %d", ret);
+      return -ENOMEM;
+    }
+
+    ret = FillBuffer();
+    if (ret != 0) {
+      buffer_allocator_->FreeBuffer(&buffer_info_);
+      return ret;
+    }
+
+    layer->input_buffer.width = buffer_info_.alloc_buffer_info.aligned_width;
+    layer->input_buffer.height = buffer_info_.alloc_buffer_info.aligned_height;
+    layer->input_buffer.size = buffer_info_.alloc_buffer_info.size;
+    layer->input_buffer.planes[0].fd = buffer_info_.alloc_buffer_info.fd;
+    layer->input_buffer.planes[0].stride = buffer_info_.alloc_buffer_info.stride;
+    layer->input_buffer.format = buffer_info_.buffer_config.format;
+
+    DLOGI("Input buffer WxH %dx%d format %s size %d fd %d stride %d", layer->input_buffer.width,
+          layer->input_buffer.height, GetFormatString(layer->input_buffer.format),
+          layer->input_buffer.size, layer->input_buffer.planes[0].fd,
+          layer->input_buffer.planes[0].stride);
+  }
+
+  return 0;
+}
+
+int HWCDisplayExternalTest::DeinitLayer(Layer *layer) {
+  if (layer->composition != kCompositionGPUTarget) {
+    int ret = buffer_allocator_->FreeBuffer(&buffer_info_);
+    if (ret != 0) {
+      DLOGE("Buffer deallocation failed. ret: %d", ret);
+      return -ENOMEM;
+    }
+  }
+
+  return 0;
+}
+
+int HWCDisplayExternalTest::CreateLayerStack() {
+  for (uint32_t i = 0; i < (kTestLayerCnt + 1 /* one dummy gpu_target layer */); i++) {
+    Layer *layer = new Layer();
+
+    if (i == kTestLayerCnt) {
+      layer->composition = kCompositionGPUTarget;
+    }
+
+    int ret = InitLayer(layer);
+    if (ret != 0) {
+      delete layer;
+      return ret;
+    }
+    layer_stack_.layers.push_back(layer);
+  }
+
+  return 0;
+}
+
+int HWCDisplayExternalTest::DestroyLayerStack() {
+  for (uint32_t i = 0; i < UINT32(layer_stack_.layers.size()); i++) {
+    Layer *layer = layer_stack_.layers.at(i);
+    int ret = DeinitLayer(layer);
+    if (ret != 0) {
+      return ret;
+    }
+
+    delete layer;
+  }
+
+  layer_stack_.layers = {};
+
+  return 0;
+}
+
+int HWCDisplayExternalTest::PostCommit(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  // Do no call flush on errors, if a successful buffer is never submitted.
+  if (flush_ && flush_on_error_) {
+    display_intf_->Flush();
+  }
+
+  if (!flush_) {
+    for (size_t i = 0; i < layer_stack_.layers.size(); i++) {
+      Layer *layer = layer_stack_.layers.at(i);
+      LayerBuffer &layer_buffer = layer->input_buffer;
+
+      close(layer_buffer.release_fence_fd);
+      layer_buffer.release_fence_fd = -1;
+    }
+
+    close(layer_stack_.retire_fence_fd);
+    layer_stack_.retire_fence_fd = -1;
+    content_list->retireFenceFd = -1;
+  }
+
+  flush_ = false;
+
+  return status;
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/hwc/hwc_display_external_test.h b/sdm845/sdm/libs/hwc/hwc_display_external_test.h
new file mode 100644
index 0000000..050823e
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_display_external_test.h
@@ -0,0 +1,102 @@
+/*
+* Copyright (c) 2017, 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_TEST_H__
+#define __HWC_DISPLAY_EXTERNAL_TEST_H__
+
+#include<bitset>
+
+#include "hwc_display.h"
+#include "hwc_buffer_allocator.h"
+
+namespace sdm {
+
+class HWCDisplayExternalTest : public HWCDisplay {
+ public:
+  static int Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                     qService::QService *qservice,  uint32_t panel_bpp, uint32_t pattern_type,
+                     HWCDisplay **hwc_display);
+  static void Destroy(HWCDisplay *hwc_display);
+  virtual int Prepare(hwc_display_contents_1_t *content_list);
+  virtual int Commit(hwc_display_contents_1_t *content_list);
+  virtual void SetSecureDisplay(bool secure_display_active, bool force_flush);
+  virtual int Perform(uint32_t operation, ...);
+
+ protected:
+  HWCBufferAllocator *buffer_allocator_ = NULL;
+  BufferInfo buffer_info_ = {};
+  uint32_t panel_bpp_ = 0;
+  uint32_t pattern_type_ = 0;
+
+  enum ColorPatternType {
+    kPatternNone = 0,
+    kPatternColorRamp,
+    kPatternBWVertical,
+    kPatternColorSquare,
+  };
+
+  enum DisplayBpp {
+    kDisplayBpp18 = 18,
+    kDisplayBpp24 = 24,
+    kDisplayBpp30 = 30,
+  };
+
+  enum ColorRamp {
+    kColorRedRamp = 0,
+    kColorGreenRamp = 1,
+    kColorBlueRamp = 2,
+    kColorWhiteRamp = 3,
+  };
+
+  enum Colors {
+    kColorBlack = 0,
+    kColorWhite = 1,
+  };
+
+ private:
+  HWCDisplayExternalTest(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                         qService::QService *qservice, uint32_t panel_bpp, uint32_t pattern_type);
+  int Init();
+  int Deinit();
+  void DumpInputBuffer();
+  void CalcCRC(uint32_t color_value, std::bitset<16> *crc_data);
+  int FillBuffer();
+  int GetStride(LayerBufferFormat format, uint32_t width, uint32_t *stride);
+  void PixelCopy(uint32_t red, uint32_t green, uint32_t blue, uint32_t alpha, uint8_t **buffer);
+  void GenerateColorRamp(uint8_t *buffer);
+  void GenerateBWVertical(uint8_t *buffer);
+  void GenerateColorSquare(uint8_t *buffer);
+  int InitLayer(Layer *layer);
+  int DeinitLayer(Layer *layer);
+  int CreateLayerStack();
+  int DestroyLayerStack();
+  int PostCommit(hwc_display_contents_1_t *content_list);
+
+  static const uint32_t kTestLayerCnt = 1;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_DISPLAY_EXTERNAL_TEST_H__
+
diff --git a/sdm845/sdm/libs/hwc/hwc_display_null.cpp b/sdm845/sdm/libs/hwc/hwc_display_null.cpp
new file mode 100644
index 0000000..649f40c
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_display_null.cpp
@@ -0,0 +1,120 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <hardware/hwcomposer_defs.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include "hwc_display_null.h"
+
+#define __CLASS__ "HWCDisplayNull"
+
+namespace sdm {
+
+int HWCDisplayNull::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                           HWCDisplay **hwc_display) {
+  int status;
+
+  DLOGI("Null display is being created");
+  HWCDisplayNull *hwc_display_null = new HWCDisplayNull(core_intf, hwc_procs);
+
+  status = hwc_display_null->Init();
+  if (status) {
+    delete hwc_display_null;
+    return status;
+  }
+
+  *hwc_display = hwc_display_null;
+
+  return 0;
+}
+
+void HWCDisplayNull::Destroy(HWCDisplay *hwc_display) {
+  DLOGI("Null display is being destroyed");
+  hwc_display->Deinit();
+  delete hwc_display;
+}
+
+// We pass the display type as HWC_DISPLAY_PRIMARY to HWCDisplay, but since we override
+// and don't chain to HWCDisplay::Init(), that type does not actually get used.
+HWCDisplayNull::HWCDisplayNull(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
+  : HWCDisplay(core_intf, hwc_procs, kPrimary, HWC_DISPLAY_PRIMARY, false, NULL,
+               DISPLAY_CLASS_NULL) {
+}
+
+int HWCDisplayNull::Init() {
+  // Don't call HWCDisplay::Init() for null display, we don't want the chain of
+  // DisplayPrimary / HWPrimary etc objects to be created.
+  return 0;
+}
+
+int HWCDisplayNull::Deinit() {
+  return 0;
+}
+
+int HWCDisplayNull::Prepare(hwc_display_contents_1_t *content_list) {
+  for (size_t i = 0; i < content_list->numHwLayers; i++) {
+    if (content_list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET ||
+        content_list->hwLayers[i].compositionType == HWC_BACKGROUND) {
+      continue;
+    }
+
+    content_list->hwLayers[i].compositionType = HWC_OVERLAY;
+  }
+
+  return 0;
+}
+
+int HWCDisplayNull::Commit(hwc_display_contents_1_t *content_list) {
+  // HWCSession::Commit (from where this is called) already closes all the acquire
+  // fences once we return from here. So no need to close acquire fences here.
+  for (size_t i = 0; i < content_list->numHwLayers; i++) {
+    content_list->hwLayers[i].releaseFenceFd = -1;
+  }
+
+  return 0;
+}
+
+#define NULL_DISPLAY_FPS 60
+
+int HWCDisplayNull::GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
+                                         int32_t *values) {
+  for (int i = 0; display_attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
+    // We fake display resolution as 1080P by default, though it can be overriden through a call to
+    // SetResolution(), and DPI as 160, though what the DPI value does is not clear
+    switch (display_attributes[i]) {
+    case HWC_DISPLAY_VSYNC_PERIOD:
+      values[i] = INT32(1000000000L / NULL_DISPLAY_FPS);
+      break;
+    case HWC_DISPLAY_WIDTH:
+      values[i] = static_cast<int32_t>(x_res_);
+      break;
+    case HWC_DISPLAY_HEIGHT:
+      values[i] = static_cast<int32_t>(y_res_);
+      break;
+    }
+  }
+  return 0;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc/hwc_display_null.h b/sdm845/sdm/libs/hwc/hwc_display_null.h
new file mode 100644
index 0000000..f1e0e5e
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_display_null.h
@@ -0,0 +1,106 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_DISPLAY_NULL_H__
+#define __HWC_DISPLAY_NULL_H__
+
+#include <qdMetaData.h>
+#include <gralloc_priv.h>
+#include "hwc_display.h"
+
+namespace sdm {
+
+class HWCDisplayNull : public HWCDisplay {
+ public:
+  static int Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                    HWCDisplay **hwc_display);
+  static void Destroy(HWCDisplay *hwc_display);
+  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 EventControl(int event, int enable) { return 0; }
+  virtual int SetPowerMode(int mode) { return 0; }
+
+  // Framebuffer configurations
+  virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs) {
+    return HWCDisplay::GetDisplayConfigs(configs, num_configs);
+  }
+
+  virtual int GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
+                                   int32_t *values);
+  virtual int GetActiveConfig() { return 0; }
+  virtual int SetActiveConfig(int index) { return -1; }
+
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms) { return; }
+  virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) { return; }
+  virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages) { return kErrorNone; }
+  virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) { return kErrorNone; }
+  virtual uint32_t GetLastPowerMode() { return 0; }
+  virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels) { return 0; }
+
+  virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+    *x_pixels = x_res_;
+    *y_pixels = y_res_;
+  }
+
+  virtual void GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+    *x_pixels = x_res_;
+    *y_pixels = y_res_;
+  }
+
+  virtual int SetDisplayStatus(uint32_t display_status) { return 0; }
+  virtual int OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) { return 0; }
+  virtual int Perform(uint32_t operation, ...) { return 0; }
+  virtual int SetCursorPosition(int x, int y) { return 0; }
+  virtual void SetSecureDisplay(bool secure_display_active, bool force_flush) { return; }
+
+  // Display Configurations
+  virtual int SetActiveDisplayConfig(int config) { return 0; }
+  virtual int GetActiveDisplayConfig(uint32_t *config) { return -1; }
+  virtual int GetDisplayConfigCount(uint32_t *count) { return -1; }
+  virtual int GetDisplayAttributesForConfig(int config,
+                                            DisplayConfigVariableInfo *display_attributes) {
+    return -1;
+  }
+  virtual bool IsValidContentList(hwc_display_contents_1_t *content_list) {
+    return true;
+  }
+
+  void SetResolution(uint32_t x_res, uint32_t y_res) {
+    x_res_ = x_res;
+    y_res_ = y_res;
+  }
+
+
+ private:
+  HWCDisplayNull(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
+  uint32_t x_res_ = 1920;
+  uint32_t y_res_ = 1080;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_DISPLAY_NULL_H__
+
diff --git a/sdm845/sdm/libs/hwc/hwc_display_primary.cpp b/sdm845/sdm/libs/hwc/hwc_display_primary.cpp
new file mode 100644
index 0000000..8d6f31b
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_display_primary.cpp
@@ -0,0 +1,563 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <sync/sync.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+
+#include <gr.h>
+#include "hwc_display_primary.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayPrimary"
+
+namespace sdm {
+
+int HWCDisplayPrimary::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+                              hwc_procs_t const **hwc_procs, qService::QService *qservice,
+                              HWCDisplay **hwc_display) {
+  int status = 0;
+  uint32_t primary_width = 0;
+  uint32_t primary_height = 0;
+
+  HWCDisplay *hwc_display_primary = new HWCDisplayPrimary(core_intf, buffer_allocator,
+                                                          hwc_procs, qservice);
+  status = hwc_display_primary->Init();
+  if (status) {
+    delete hwc_display_primary;
+    return status;
+  }
+
+  hwc_display_primary->GetMixerResolution(&primary_width, &primary_height);
+  int width = 0, height = 0;
+  HWCDebugHandler::Get()->GetProperty("sdm.fb_size_width", &width);
+  HWCDebugHandler::Get()->GetProperty("sdm.fb_size_height", &height);
+  if (width > 0 && height > 0) {
+    primary_width = UINT32(width);
+    primary_height = UINT32(height);
+  }
+
+  status = hwc_display_primary->SetFrameBufferResolution(primary_width, primary_height);
+  if (status) {
+    Destroy(hwc_display_primary);
+    return status;
+  }
+
+  *hwc_display = hwc_display_primary;
+
+  return status;
+}
+
+void HWCDisplayPrimary::Destroy(HWCDisplay *hwc_display) {
+  hwc_display->Deinit();
+  delete hwc_display;
+}
+
+HWCDisplayPrimary::HWCDisplayPrimary(CoreInterface *core_intf,
+                                     BufferAllocator *buffer_allocator,
+                                     hwc_procs_t const **hwc_procs,
+                                     qService::QService *qservice)
+  : HWCDisplay(core_intf, hwc_procs, kPrimary, HWC_DISPLAY_PRIMARY, true, qservice,
+               DISPLAY_CLASS_PRIMARY), buffer_allocator_(buffer_allocator) {
+}
+
+int HWCDisplayPrimary::Init() {
+  cpu_hint_.Init(static_cast<HWCDebugHandler*>(HWCDebugHandler::Get()));
+
+  use_metadata_refresh_rate_ = true;
+  int disable_metadata_dynfps = 0;
+  HWCDebugHandler::Get()->GetProperty("persist.metadata_dynfps.disable", &disable_metadata_dynfps);
+  if (disable_metadata_dynfps) {
+    use_metadata_refresh_rate_ = false;
+  }
+
+  int status = HWCDisplay::Init();
+  if (status) {
+    return status;
+  }
+  color_mode_ = new HWCColorMode(display_intf_);
+  color_mode_->Init();
+
+  return status;
+}
+
+int HWCDisplayPrimary::Deinit() {
+  color_mode_->DeInit();
+  delete color_mode_;
+  color_mode_ = NULL;
+
+  return HWCDisplay::Deinit();
+}
+
+
+void HWCDisplayPrimary::ProcessBootAnimCompleted(hwc_display_contents_1_t *list) {
+  uint32_t numBootUpLayers = 0;
+
+  numBootUpLayers = static_cast<uint32_t>(Debug::GetBootAnimLayerCount());
+
+  if (numBootUpLayers == 0) {
+    numBootUpLayers = 2;
+  }
+  /* All other checks namely "init.svc.bootanim" or
+  * HWC_GEOMETRY_CHANGED fail in correctly identifying the
+  * exact bootup transition to homescreen
+  */
+  char cryptoState[PROPERTY_VALUE_MAX];
+  char voldDecryptState[PROPERTY_VALUE_MAX];
+  bool isEncrypted = false;
+  bool main_class_services_started = false;
+  if (property_get("ro.crypto.state", cryptoState, "unencrypted")) {
+    if (!strcmp(cryptoState, "encrypted")) {
+      isEncrypted = true;
+      if (property_get("vold.decrypt", voldDecryptState, "") &&
+            !strcmp(voldDecryptState, "trigger_restart_framework"))
+        main_class_services_started = true;
+    }
+  }
+  if ((!isEncrypted ||(isEncrypted && main_class_services_started)) &&
+    (list->numHwLayers > numBootUpLayers)) {
+    boot_animation_completed_ = true;
+    // Applying default mode after bootanimation is finished And
+    // If Data is Encrypted, it is ready for access.
+    if (display_intf_)
+      display_intf_->ApplyDefaultDisplayMode();
+  }
+}
+
+int HWCDisplayPrimary::Prepare(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+  DisplayError error = kErrorNone;
+
+  if (!boot_animation_completed_)
+    ProcessBootAnimCompleted(content_list);
+
+  if (display_paused_) {
+    MarkLayersForGPUBypass(content_list);
+    return status;
+  }
+
+  status = AllocateLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  status = PrePrepareLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
+
+  if (frame_capture_buffer_queued_ || pending_output_dump) {
+    // RHS values were set in FrameCaptureAsync() called from a binder thread. They are picked up
+    // here in a subsequent draw round.
+    layer_stack_.output_buffer = &output_buffer_;
+    layer_stack_.flags.post_processed_output = post_processed_output_;
+  }
+
+  uint32_t num_updating_layers = GetUpdatingLayersCount(UINT32(content_list->numHwLayers - 1));
+  bool one_updating_layer = (num_updating_layers == 1);
+
+  if (num_updating_layers != 0) {
+    ToggleCPUHint(one_updating_layer);
+  }
+
+  uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
+  bool final_rate = force_refresh_rate_ ? true : false;
+  error = display_intf_->SetRefreshRate(refresh_rate, final_rate);
+  if (error == kErrorNone) {
+    // On success, set current refresh rate to new refresh rate
+    current_refresh_rate_ = refresh_rate;
+  }
+
+  if (content_list->numHwLayers <= 1) {
+    flush_ = true;
+  }
+
+  status = PrepareLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  return 0;
+}
+
+int HWCDisplayPrimary::Commit(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  DisplayConfigFixedInfo display_config;
+  display_intf_->GetConfig(&display_config);
+  if (content_list->numHwLayers <= 1 && display_config.is_cmdmode) {
+    DLOGV("Skipping null commit on cmd mode panel");
+    flush_ = false;
+    return 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;
+    }
+
+    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;
+  }
+
+  HandleFrameOutput();
+
+  status = HWCDisplay::PostCommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  return 0;
+}
+
+int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
+  va_list args;
+  va_start(args, operation);
+  int val = va_arg(args, int32_t);
+  va_end(args);
+  switch (operation) {
+    case SET_METADATA_DYN_REFRESH_RATE:
+      SetMetaDataRefreshRateFlag(val);
+      break;
+    case SET_BINDER_DYN_REFRESH_RATE:
+      ForceRefreshRate(UINT32(val));
+      break;
+    case SET_DISPLAY_MODE:
+      SetDisplayMode(UINT32(val));
+      break;
+    case SET_QDCM_SOLID_FILL_INFO:
+      SetQDCMSolidFillInfo(true, UINT32(val));
+      break;
+    case UNSET_QDCM_SOLID_FILL_INFO:
+      SetQDCMSolidFillInfo(false, UINT32(val));
+      break;
+    default:
+      DLOGW("Invalid operation %d", operation);
+      return -EINVAL;
+  }
+
+  return 0;
+}
+
+DisplayError HWCDisplayPrimary::SetDisplayMode(uint32_t mode) {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->SetDisplayMode(mode);
+  }
+
+  return error;
+}
+
+void HWCDisplayPrimary::SetMetaDataRefreshRateFlag(bool enable) {
+  int disable_metadata_dynfps = 0;
+
+  HWCDebugHandler::Get()->GetProperty("persist.metadata_dynfps.disable", &disable_metadata_dynfps);
+  if (disable_metadata_dynfps) {
+    return;
+  }
+  use_metadata_refresh_rate_ = enable;
+}
+
+void HWCDisplayPrimary::SetQDCMSolidFillInfo(bool enable, uint32_t color) {
+  solid_fill_enable_ = enable;
+  solid_fill_color_  = color;
+}
+
+void HWCDisplayPrimary::ToggleCPUHint(bool set) {
+  if (set) {
+    cpu_hint_.Set();
+  } else {
+    cpu_hint_.Reset();
+  }
+}
+
+void HWCDisplayPrimary::SetSecureDisplay(bool secure_display_active, bool force_flush) {
+  if (secure_display_active_ != secure_display_active) {
+    // Skip Prepare and call Flush for null commit
+    DLOGI("SecureDisplay state changed from %d to %d Needs Flush!!", secure_display_active_,
+           secure_display_active);
+    secure_display_active_ = secure_display_active;
+    skip_prepare_cnt = 1;
+
+    // Issue two null commits for command mode panels when external displays are connected.
+    // Two null commits are required to handle non secure to secure transitions at 30fps.
+    // TODO(user): Need two null commits on video mode also to handle transition cases of
+    // primary at higher fps (ex60) and external at lower fps.
+
+    // Avoid flush for command mode panels when no external displays are connected.
+    // This is to avoid flicker/blink on primary during transitions.
+    DisplayConfigFixedInfo display_config;
+    display_intf_->GetConfig(&display_config);
+    if (display_config.is_cmdmode) {
+      if (force_flush) {
+        DLOGI("Issue two null commits for command mode panels");
+        skip_prepare_cnt = 2;
+      } else {
+        DLOGI("Avoid flush for command mode panel when no external displays are connected");
+        skip_prepare_cnt = 0;
+      }
+    }
+  }
+}
+
+void HWCDisplayPrimary::ForceRefreshRate(uint32_t refresh_rate) {
+  if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
+       force_refresh_rate_ == refresh_rate) {
+    // Cannot honor force refresh rate, as its beyond the range or new request is same
+    return;
+  }
+
+  const hwc_procs_t *hwc_procs = *hwc_procs_;
+  force_refresh_rate_ = refresh_rate;
+
+  hwc_procs->invalidate(hwc_procs);
+
+  return;
+}
+
+uint32_t HWCDisplayPrimary::GetOptimalRefreshRate(bool one_updating_layer) {
+  if (force_refresh_rate_) {
+    return force_refresh_rate_;
+  } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
+    return metadata_refresh_rate_;
+  }
+
+  return max_refresh_rate_;
+}
+
+DisplayError HWCDisplayPrimary::Refresh() {
+  const hwc_procs_t *hwc_procs = *hwc_procs_;
+  DisplayError error = kErrorNone;
+
+  if (!hwc_procs) {
+    return kErrorParameters;
+  }
+
+  hwc_procs->invalidate(hwc_procs);
+
+  return error;
+}
+
+void HWCDisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+  display_intf_->SetIdleTimeoutMs(timeout_ms);
+}
+
+static void SetLayerBuffer(const BufferInfo& output_buffer_info, LayerBuffer *output_buffer) {
+  const BufferConfig& buffer_config = output_buffer_info.buffer_config;
+  const AllocatedBufferInfo &alloc_buffer_info = output_buffer_info.alloc_buffer_info;
+
+  output_buffer->width = alloc_buffer_info.aligned_width;
+  output_buffer->height = alloc_buffer_info.aligned_height;
+  output_buffer->unaligned_width = buffer_config.width;
+  output_buffer->unaligned_height = buffer_config.height;
+  output_buffer->format = buffer_config.format;
+  output_buffer->planes[0].fd = alloc_buffer_info.fd;
+  output_buffer->planes[0].stride = alloc_buffer_info.stride;
+}
+
+void HWCDisplayPrimary::HandleFrameOutput() {
+  if (frame_capture_buffer_queued_) {
+    HandleFrameCapture();
+  } else if (dump_output_to_file_) {
+    HandleFrameDump();
+  }
+}
+
+void HWCDisplayPrimary::HandleFrameCapture() {
+  if (output_buffer_.release_fence_fd >= 0) {
+    frame_capture_status_ = sync_wait(output_buffer_.release_fence_fd, 1000);
+    ::close(output_buffer_.release_fence_fd);
+    output_buffer_.release_fence_fd = -1;
+  }
+
+  frame_capture_buffer_queued_ = false;
+  post_processed_output_ = false;
+  output_buffer_ = {};
+}
+
+void HWCDisplayPrimary::HandleFrameDump() {
+  if (dump_frame_count_ && output_buffer_.release_fence_fd >= 0) {
+    int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
+    ::close(output_buffer_.release_fence_fd);
+    output_buffer_.release_fence_fd = -1;
+    if (ret < 0) {
+      DLOGE("sync_wait error errno = %d, desc = %s", errno,  strerror(errno));
+    } else {
+      DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence_fd);
+    }
+  }
+
+  if (0 == dump_frame_count_) {
+    dump_output_to_file_ = false;
+    // Unmap and Free buffer
+    if (munmap(output_buffer_base_, output_buffer_info_.alloc_buffer_info.size) != 0) {
+      DLOGE("unmap failed with err %d", errno);
+    }
+    if (buffer_allocator_->FreeBuffer(&output_buffer_info_) != 0) {
+      DLOGE("FreeBuffer failed");
+    }
+
+    post_processed_output_ = false;
+    output_buffer_ = {};
+    output_buffer_info_ = {};
+    output_buffer_base_ = nullptr;
+  }
+}
+
+void HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+  HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
+  dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
+  DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
+
+  if (!count || !dump_output_to_file_) {
+    return;
+  }
+
+  // Allocate and map output buffer
+  output_buffer_info_ = {};
+  // Since we dump DSPP output use Panel resolution.
+  GetPanelResolution(&output_buffer_info_.buffer_config.width,
+                     &output_buffer_info_.buffer_config.height);
+  output_buffer_info_.buffer_config.format = kFormatRGB888;
+  output_buffer_info_.buffer_config.buffer_count = 1;
+  if (buffer_allocator_->AllocateBuffer(&output_buffer_info_) != 0) {
+    DLOGE("Buffer allocation failed");
+    output_buffer_info_ = {};
+    return;
+  }
+
+  void *buffer = mmap(NULL, output_buffer_info_.alloc_buffer_info.size,
+                      PROT_READ | PROT_WRITE,
+                      MAP_SHARED, output_buffer_info_.alloc_buffer_info.fd, 0);
+
+  if (buffer == MAP_FAILED) {
+    DLOGE("mmap failed with err %d", errno);
+    buffer_allocator_->FreeBuffer(&output_buffer_info_);
+    output_buffer_info_ = {};
+    return;
+  }
+
+  output_buffer_base_ = buffer;
+  post_processed_output_ = true;
+  DisablePartialUpdateOneFrame();
+}
+
+int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo& output_buffer_info,
+                                         bool post_processed_output) {
+  // Note: This function is called in context of a binder thread and a lock is already held
+  if (output_buffer_info.alloc_buffer_info.fd < 0) {
+    DLOGE("Invalid fd %d", output_buffer_info.alloc_buffer_info.fd);
+    return -1;
+  }
+
+  auto panel_width = 0u;
+  auto panel_height = 0u;
+  auto fb_width = 0u;
+  auto fb_height = 0u;
+
+  GetPanelResolution(&panel_width, &panel_height);
+  GetFrameBufferResolution(&fb_width, &fb_height);
+
+  if (post_processed_output && (output_buffer_info.buffer_config.width < panel_width ||
+                                output_buffer_info.buffer_config.height < panel_height)) {
+    DLOGE("Buffer dimensions should not be less than panel resolution");
+    return -1;
+  } else if (!post_processed_output && (output_buffer_info.buffer_config.width < fb_width ||
+                                        output_buffer_info.buffer_config.height < fb_height)) {
+    DLOGE("Buffer dimensions should not be less than FB resolution");
+    return -1;
+  }
+
+  SetLayerBuffer(output_buffer_info, &output_buffer_);
+  post_processed_output_ = post_processed_output;
+  frame_capture_buffer_queued_ = true;
+  // Status is only cleared on a new call to dump and remains valid otherwise
+  frame_capture_status_ = -EAGAIN;
+  DisablePartialUpdateOneFrame();
+
+  return 0;
+}
+
+DisplayError HWCDisplayPrimary::SetDetailEnhancerConfig(
+                                    const DisplayDetailEnhancerData &de_data) {
+  DisplayError error = kErrorNotSupported;
+  if (display_intf_) {
+    error = display_intf_->SetDetailEnhancerData(de_data);
+  }
+  return error;
+}
+
+DisplayError HWCDisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->ControlPartialUpdate(enable, pending);
+  }
+
+  return error;
+}
+
+DisplayError HWCDisplayPrimary::DisablePartialUpdateOneFrame() {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->DisablePartialUpdateOneFrame();
+  }
+
+  return error;
+}
+
+DisplayError HWCDisplayPrimary::SetMixerResolution(uint32_t width, uint32_t height) {
+  return display_intf_->SetMixerResolution(width, height);
+}
+
+DisplayError HWCDisplayPrimary::GetMixerResolution(uint32_t *width, uint32_t *height) {
+  return display_intf_->GetMixerResolution(width, height);
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/hwc/hwc_display_primary.h b/sdm845/sdm/libs/hwc/hwc_display_primary.h
new file mode 100644
index 0000000..e937980
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_display_primary.h
@@ -0,0 +1,90 @@
+/*
+* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_DISPLAY_PRIMARY_H__
+#define __HWC_DISPLAY_PRIMARY_H__
+
+#include "cpuhint.h"
+#include "hwc_display.h"
+
+namespace sdm {
+
+class HWCDisplayPrimary : public HWCDisplay {
+ public:
+  static int Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+                    hwc_procs_t const **hwc_procs, qService::QService *qservice,
+                    HWCDisplay **hwc_display);
+  static void Destroy(HWCDisplay *hwc_display);
+  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 Perform(uint32_t operation, ...);
+  virtual void SetSecureDisplay(bool secure_display_active, bool force_flush);
+  virtual DisplayError Refresh();
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+  virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+  virtual int FrameCaptureAsync(const BufferInfo& output_buffer_info, bool post_processed);
+  virtual int GetFrameCaptureStatus() { return frame_capture_status_; }
+  virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data);
+  virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
+
+ private:
+  HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+                    hwc_procs_t const **hwc_procs, qService::QService *qservice);
+  void SetMetaDataRefreshRateFlag(bool enable);
+  virtual DisplayError SetDisplayMode(uint32_t mode);
+  virtual DisplayError DisablePartialUpdateOneFrame();
+  void ProcessBootAnimCompleted(hwc_display_contents_1_t *content_list);
+  void SetQDCMSolidFillInfo(bool enable, uint32_t color);
+  void ToggleCPUHint(bool set);
+  void ForceRefreshRate(uint32_t refresh_rate);
+  uint32_t GetOptimalRefreshRate(bool one_updating_layer);
+  void HandleFrameOutput();
+  void HandleFrameCapture();
+  void HandleFrameDump();
+  DisplayError SetMixerResolution(uint32_t width, uint32_t height);
+  DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+
+  BufferAllocator *buffer_allocator_ = nullptr;
+  CPUHint cpu_hint_;
+
+  // Primary output buffer configuration
+  LayerBuffer output_buffer_ = {};
+  bool post_processed_output_ = false;
+
+  // Members for 1 frame capture in a client provided buffer
+  bool frame_capture_buffer_queued_ = false;
+  int frame_capture_status_ = -EAGAIN;
+
+  // Members for N frame output dump to file
+  bool dump_output_to_file_ = false;
+  BufferInfo output_buffer_info_ = {};
+  void *output_buffer_base_ = nullptr;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_DISPLAY_PRIMARY_H__
+
diff --git a/sdm845/sdm/libs/hwc/hwc_display_virtual.cpp b/sdm845/sdm/libs/hwc/hwc_display_virtual.cpp
new file mode 100644
index 0000000..0279fc2
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_display_virtual.cpp
@@ -0,0 +1,334 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <sync/sync.h>
+#include <stdarg.h>
+#include <gr.h>
+
+#include "hwc_display_virtual.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayVirtual"
+
+namespace sdm {
+
+int HWCDisplayVirtual::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                              uint32_t primary_width, uint32_t primary_height,
+                              hwc_display_contents_1_t *content_list,
+                              HWCDisplay **hwc_display) {
+  int status = 0;
+  HWCDisplayVirtual *hwc_display_virtual = new HWCDisplayVirtual(core_intf, hwc_procs);
+  uint32_t virtual_width = 0, virtual_height = 0;
+
+  status = hwc_display_virtual->Init();
+  if (status) {
+    delete hwc_display_virtual;
+    return status;
+  }
+
+  status = hwc_display_virtual->SetPowerMode(HWC_POWER_MODE_NORMAL);
+  if (status) {
+    Destroy(hwc_display_virtual);
+    return status;
+  }
+
+  // TODO(user): Need to update resolution(and not aligned resolution) on writeback.
+  status = hwc_display_virtual->SetOutputSliceFromMetadata(content_list);
+  if (status) {
+    Destroy(hwc_display_virtual);
+    return status;
+  }
+
+  hwc_display_virtual->GetMixerResolution(&virtual_width, &virtual_height);
+
+  if (content_list->numHwLayers < 1) {
+    Destroy(hwc_display_virtual);
+    return -1;
+  }
+
+  hwc_layer_1_t &fb_layer = content_list->hwLayers[content_list->numHwLayers-1];
+  int fb_width = fb_layer.displayFrame.right - fb_layer.displayFrame.left;
+  int fb_height = fb_layer.displayFrame.bottom - fb_layer.displayFrame.top;
+
+  status = hwc_display_virtual->SetFrameBufferResolution(UINT32(fb_width), UINT32(fb_height));
+
+  if (status) {
+    Destroy(hwc_display_virtual);
+    return status;
+  }
+
+  *hwc_display = static_cast<HWCDisplay *>(hwc_display_virtual);
+
+  return 0;
+}
+
+void HWCDisplayVirtual::Destroy(HWCDisplay *hwc_display) {
+  hwc_display->Deinit();
+  delete hwc_display;
+}
+
+HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
+  : HWCDisplay(core_intf, hwc_procs, kVirtual, HWC_DISPLAY_VIRTUAL, false, NULL,
+               DISPLAY_CLASS_VIRTUAL) {
+}
+
+int HWCDisplayVirtual::Init() {
+  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_;
+    output_buffer_ = NULL;
+  }
+
+  return status;
+}
+
+int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  status = SetOutputSliceFromMetadata(content_list);
+  if (status) {
+    return status;
+  }
+
+  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 = PrePrepareLayerStack(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_) {
+    DisplayError error = display_intf_->Flush();
+    if (error != kErrorNone) {
+      DLOGE("Flush failed. Error = %d", error);
+    }
+    return status;
+  }
+
+  CommitOutputBufferParams(content_list);
+
+  status = HWCDisplay::CommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  if (dump_frame_count_ && !flush_ && dump_output_layer_) {
+    const private_handle_t *output_handle = (const private_handle_t *)(content_list->outbuf);
+    if (output_handle && output_handle->base) {
+      BufferInfo buffer_info;
+      buffer_info.buffer_config.width = static_cast<uint32_t>(output_handle->width);
+      buffer_info.buffer_config.height = static_cast<uint32_t>(output_handle->height);
+      buffer_info.buffer_config.format = GetSDMFormat(output_handle->format, output_handle->flags);
+      buffer_info.alloc_buffer_info.size = static_cast<uint32_t>(output_handle->size);
+      DumpOutputBuffer(buffer_info, reinterpret_cast<void *>(output_handle->base),
+                       layer_stack_.retire_fence_fd);
+    }
+  }
+
+  status = HWCDisplay::PostCommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  return 0;
+}
+
+int HWCDisplayVirtual::SetOutputSliceFromMetadata(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) {
+    int output_handle_format = output_handle->format;
+    if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
+      output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
+    }
+
+    LayerBufferFormat format = GetSDMFormat(output_handle_format, output_handle->flags);
+    if (format == kFormatInvalid) {
+      return -EINVAL;
+    }
+
+    int active_width;
+    int active_height;
+
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, active_width,
+                                                          active_height);
+
+    if ((active_width != INT(output_buffer_->width)) ||
+        (active_height!= INT(output_buffer_->height)) ||
+        (format != output_buffer_->format)) {
+      // Populate virtual display attributes based on displayFrame of FBT.
+      // For DRC, use width and height populated in metadata (unaligned values)
+      // for setting attributes of virtual display. This is needed because if
+      // we use aligned width and height, scaling will be required for FBT layer.
+      DisplayConfigVariableInfo variable_info;
+      hwc_layer_1_t &fbt_layer = content_list->hwLayers[content_list->numHwLayers-1];
+      hwc_rect_t &frame = fbt_layer.displayFrame;
+      int fbt_width = frame.right - frame.left;
+      int fbt_height = frame.bottom - frame.top;
+      const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(output_handle->base_metadata);
+      if (meta_data && meta_data->operation & UPDATE_BUFFER_GEOMETRY) {
+        variable_info.x_pixels = UINT32(meta_data->bufferDim.sliceWidth);
+        variable_info.y_pixels = UINT32(meta_data->bufferDim.sliceHeight);
+      } else {
+        variable_info.x_pixels = UINT32(fbt_width);
+        variable_info.y_pixels = UINT32(fbt_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) {
+  const private_handle_t *output_handle =
+        static_cast<const private_handle_t *>(content_list->outbuf);
+
+  if (output_handle) {
+    int output_handle_format = output_handle->format;
+
+    if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
+      output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
+    }
+
+    output_buffer_->format = GetSDMFormat(output_handle_format, output_handle->flags);
+
+    if (output_buffer_->format == kFormatInvalid) {
+      return -EINVAL;
+    }
+
+    int aligned_width, aligned_height;
+    int unaligned_width, unaligned_height;
+
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, aligned_width,
+                                                          aligned_height);
+    AdrenoMemInfo::getInstance().getUnalignedWidthAndHeight(output_handle, unaligned_width,
+                                                            unaligned_height);
+
+    output_buffer_->width = UINT32(aligned_width);
+    output_buffer_->height = UINT32(aligned_height);
+    output_buffer_->unaligned_width = UINT32(unaligned_width);
+    output_buffer_->unaligned_height = UINT32(unaligned_height);
+    output_buffer_->flags.secure = 0;
+    output_buffer_->flags.video = 0;
+
+    const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(output_handle->base_metadata);
+    if (meta_data && SetCSC(meta_data, &output_buffer_->color_metadata) != kErrorNone) {
+      return kErrorNotSupported;
+    }
+
+    // TZ Protected Buffer - L1
+    if (output_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+      output_buffer_->flags.secure = 1;
+    }
+  }
+
+  layer_stack_.output_buffer = output_buffer_;
+
+  return 0;
+}
+
+void HWCDisplayVirtual::CommitOutputBufferParams(hwc_display_contents_1_t *content_list) {
+  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) {
+    // 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 = UINT32(output_handle->width);
+  }
+}
+
+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_);
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/hwc/hwc_display_virtual.h b/sdm845/sdm/libs/hwc/hwc_display_virtual.h
new file mode 100644
index 0000000..77e16d5
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_display_virtual.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2014,2016 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __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:
+  static int Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                    uint32_t primary_width, uint32_t primary_height,
+                    hwc_display_contents_1_t *content_list, HWCDisplay **hwc_display);
+  static void Destroy(HWCDisplay *hwc_display);
+  static bool IsValidContentList(hwc_display_contents_1_t *content_list);
+  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 void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+
+ private:
+  HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
+  int SetOutputBuffer(hwc_display_contents_1_t *content_list);
+  int SetOutputSliceFromMetadata(hwc_display_contents_1_t *content_list);
+  void CommitOutputBufferParams(hwc_display_contents_1_t *content_list);
+
+  bool dump_output_layer_ = false;
+  LayerBuffer *output_buffer_ = NULL;
+};
+
+inline bool HWCDisplayVirtual::IsValidContentList(hwc_display_contents_1_t *content_list) {
+  return (content_list && content_list->numHwLayers > 0 && content_list->outbuf);
+}
+
+}  // namespace sdm
+
+#endif  // __HWC_DISPLAY_VIRTUAL_H__
+
diff --git a/sdm845/sdm/libs/hwc/hwc_session.cpp b/sdm845/sdm/libs/hwc/hwc_session.cpp
new file mode 100644
index 0000000..98e14ee
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_session.cpp
@@ -0,0 +1,1743 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <private/color_params.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 <utils/debug.h>
+#include <sync/sync.h>
+#include <profiler.h>
+#include <bitset>
+#include <vector>
+
+#include "hwc_buffer_allocator.h"
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_session.h"
+#include "hwc_debugger.h"
+#include "hwc_display_null.h"
+#include "hwc_display_primary.h"
+#include "hwc_display_virtual.h"
+#include "hwc_display_external_test.h"
+#include "qd_utils.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_;
+
+static void Invalidate(const struct hwc_procs *procs) {
+}
+
+static void VSync(const struct hwc_procs* procs, int disp, int64_t timestamp) {
+}
+
+static void Hotplug(const struct hwc_procs* procs, int disp, int connected) {
+}
+
+HWCSession::HWCSession(const hw_module_t *module) {
+  // By default, drop any events. Calls will be routed to SurfaceFlinger after registerProcs.
+  hwc_procs_default_.invalidate = Invalidate;
+  hwc_procs_default_.vsync = VSync;
+  hwc_procs_default_.hotplug = Hotplug;
+
+  hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
+  hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_5;
+  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;
+  hwc_composer_device_1_t::setCursorPositionAsync = SetCursorPositionAsync;
+}
+
+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> iqservice = android::interface_cast<qService::IQService>(
+                android::defaultServiceManager()->getService(android::String16(qservice_name)));
+
+  if (iqservice.get()) {
+    iqservice->connect(android::sp<qClient::IQClient>(this));
+    qservice_ = reinterpret_cast<qService::QService* >(iqservice.get());
+  } else {
+    DLOGE("Failed to acquire %s", qservice_name);
+    return -EINVAL;
+  }
+
+  DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
+                                                 &buffer_sync_handler_, &socket_handler_,
+                                                 &core_intf_);
+  if (error != kErrorNone) {
+    DLOGE("Display core initialization failed. Error = %d", error);
+    return -EINVAL;
+  }
+
+  SCOPE_LOCK(uevent_locker_);
+
+  if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) {
+    DLOGE("Failed to start = %s, error = %s", uevent_thread_name_, strerror(errno));
+    CoreInterface::DestroyCore();
+    return -errno;
+  }
+
+  // Wait for uevent_init() to happen and let the uevent thread wait for uevents, so that hdmi
+  // connect/disconnect events won't be missed
+  uevent_locker_.Wait();
+
+  // Read which display is first, and create it and store it in primary slot
+  HWDisplayInterfaceInfo hw_disp_info;
+  error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
+  if (error == kErrorNone) {
+    if (hw_disp_info.type == kHDMI) {
+      // HDMI is primary display. If already connected, then create it and store in
+      // primary display slot. If not connected, create a NULL display for now.
+      HWCDebugHandler::Get()->SetProperty("persist.sys.is_hdmi_primary", "1");
+      is_hdmi_primary_ = true;
+      if (hw_disp_info.is_connected) {
+        status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, 0, 0, false);
+        is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY);
+      } else {
+        // NullDisplay simply closes all its fences, and advertizes a standard
+        // resolution to SurfaceFlinger
+        status = HWCDisplayNull::Create(core_intf_, &hwc_procs_,
+                                        &hwc_display_[HWC_DISPLAY_PRIMARY]);
+      }
+    } else {
+      // Create and power on primary display
+      status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &hwc_procs_, qservice_,
+                                         &hwc_display_[HWC_DISPLAY_PRIMARY]);
+    }
+  } else {
+    // Create and power on primary display
+    status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &hwc_procs_, qservice_,
+                                       &hwc_display_[HWC_DISPLAY_PRIMARY]);
+  }
+
+  if (status) {
+    CoreInterface::DestroyCore();
+    uevent_thread_exit_ = true;
+    pthread_join(uevent_thread_, NULL);
+    return status;
+  }
+
+  color_mgr_ = HWCColorManager::CreateColorManager();
+  if (!color_mgr_) {
+    DLOGW("Failed to load HWCColorManager.");
+  }
+
+  connected_displays_[HWC_DISPLAY_PRIMARY] = 1;
+  struct rlimit fd_limit = {};
+  getrlimit(RLIMIT_NOFILE, &fd_limit);
+  fd_limit.rlim_cur = fd_limit.rlim_cur * 2;
+  auto err = setrlimit(RLIMIT_NOFILE, &fd_limit);
+  if (err) {
+    DLOGW("Unable to increase fd limit -  err: %d, %s", errno, strerror(errno));
+  }
+  return 0;
+}
+
+int HWCSession::Deinit() {
+  HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
+  hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
+  if (color_mgr_) {
+    color_mgr_->DestroyColorManager();
+  }
+  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);
+  }
+
+  connected_displays_[HWC_DISPLAY_PRIMARY] = 0;
+  return 0;
+}
+
+int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  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) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  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();
+
+  if (!device || !displays || num_displays > HWC_NUM_DISPLAY_TYPES) {
+    return -EINVAL;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  hwc_procs_t const *hwc_procs = NULL;
+  bool hotplug_connect = false;
+
+  // Hold mutex only in this scope.
+  {
+    SEQUENCE_ENTRY_SCOPE_LOCK(locker_);
+
+    hwc_procs = hwc_session->hwc_procs_;
+
+    if (hwc_session->reset_panel_) {
+      DLOGW("panel is in bad state, resetting the panel");
+      hwc_session->ResetPanel();
+    }
+
+    if (hwc_session->need_invalidate_) {
+      hwc_session->AsyncRefresh();
+      hwc_session->need_invalidate_ = false;
+    }
+
+    hwc_session->HandleSecureDisplaySession(displays);
+
+    if (hwc_session->color_mgr_) {
+      HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY];
+      if (primary_display && !hwc_session->is_hdmi_primary_) {
+        int ret = hwc_session->color_mgr_->SolidFillLayersPrepare(displays, primary_display);
+        if (ret)
+          return 0;
+      }
+    }
+
+    for (ssize_t dpy = static_cast<ssize_t>(num_displays - 1); dpy >= 0; dpy--) {
+      hwc_display_contents_1_t *content_list = displays[dpy];
+      // If external display is connected, ignore virtual display content list.
+      // If virtual display content list is valid, connect virtual display if not connected.
+      // If virtual display content list is invalid, disconnect virtual display if connected.
+      // If external display connection is pending, connect external display when virtual
+      // display is destroyed.
+      // If HDMI is primary and the output format is YUV then ignore the virtual display
+      // content list.
+      if (dpy == HWC_DISPLAY_VIRTUAL) {
+        if (hwc_session->hwc_display_[HWC_DISPLAY_EXTERNAL] ||
+                (hwc_session->is_hdmi_primary_ && hwc_session->is_hdmi_yuv_)) {
+          continue;
+        }
+
+        bool valid_content = HWCDisplayVirtual::IsValidContentList(content_list);
+        bool connected = (hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL] != NULL);
+
+        if (valid_content && !connected) {
+          hwc_session->ConnectDisplay(HWC_DISPLAY_VIRTUAL, content_list);
+        } else if (!valid_content && connected) {
+          hwc_session->DisconnectDisplay(HWC_DISPLAY_VIRTUAL);
+
+          if (hwc_session->external_pending_connect_) {
+            DLOGI("Process pending external display connection");
+            hwc_session->ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL);
+            hwc_session->external_pending_connect_ = false;
+            hotplug_connect = true;
+          }
+        }
+      }
+
+      if (hwc_session->hwc_display_[dpy]) {
+        if (!content_list) {
+          DLOGI("Display[%d] connected. content_list is null", dpy);
+        } else if (!content_list->numHwLayers) {
+          DLOGE("Display[%d] connected. numHwLayers is zero", dpy);
+        } else {
+          hwc_session->hwc_display_[dpy]->Prepare(content_list);
+        }
+      }
+    }
+  }
+
+  if (hotplug_connect) {
+    // notify client
+    hwc_procs->hotplug(hwc_procs, HWC_DISPLAY_EXTERNAL, true);
+  }
+  // Return 0, else client will go into bad state
+  return 0;
+}
+
+int HWCSession::GetVsyncPeriod(int disp) {
+  SCOPE_LOCK(locker_);
+  // default value
+  int32_t vsync_period = 1000000000l / 60;
+  const uint32_t attribute = HWC_DISPLAY_VSYNC_PERIOD;
+
+  if (hwc_display_[disp]) {
+    hwc_display_[disp]->GetDisplayAttributes(0, &attribute, &vsync_period);
+  }
+
+  return vsync_period;
+}
+
+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 || num_displays > HWC_NUM_DISPLAY_TYPES) {
+    return -EINVAL;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+
+  if (hwc_session->color_mgr_) {
+    HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY];
+    if (primary_display) {
+      int ret = hwc_session->color_mgr_->SolidFillLayersSet(displays, primary_display);
+      if (ret)
+        return 0;
+      hwc_session->color_mgr_->SetColorModeDetailEnhancer(primary_display);
+    }
+  }
+
+  for (size_t dpy = 0; dpy < num_displays; dpy++) {
+    hwc_display_contents_1_t *content_list = displays[dpy];
+
+    // Drop virtual display composition if virtual display object could not be created
+    // due to HDMI concurrency.
+    if (dpy == HWC_DISPLAY_VIRTUAL && !hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+      CloseAcquireFds(content_list);
+      if (content_list) {
+        content_list->retireFenceFd = -1;
+      }
+
+      continue;
+    }
+
+    if (hwc_session->hwc_display_[dpy]) {
+      hwc_session->hwc_display_[dpy]->Commit(content_list);
+    }
+    CloseAcquireFds(content_list);
+  }
+
+  if (hwc_session->new_bw_mode_) {
+    hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY];
+    hwc_session->new_bw_mode_ = false;
+    if (hwc_session->bw_mode_release_fd_ >= 0) {
+      close(hwc_session->bw_mode_release_fd_);
+    }
+    hwc_session->bw_mode_release_fd_ = dup(content_list->retireFenceFd);
+  }
+
+  locker_.Signal();
+
+  // This is only indicative of how many times SurfaceFlinger posts
+  // frames to the display.
+  CALC_FPS();
+
+  // Return 0, else client will go into bad state
+  return 0;
+}
+
+void HWCSession::CloseAcquireFds(hwc_display_contents_1_t *content_list) {
+  if (content_list) {
+    for (size_t i = 0; i < content_list->numHwLayers; i++) {
+      int &acquireFenceFd = content_list->hwLayers[i].acquireFenceFd;
+      if (acquireFenceFd >= 0) {
+        close(acquireFenceFd);
+        acquireFenceFd = -1;
+      }
+    }
+
+    int &outbufAcquireFenceFd = content_list->outbufAcquireFenceFd;
+    if (outbufAcquireFenceFd >= 0) {
+      close(outbufAcquireFenceFd);
+      outbufAcquireFenceFd = -1;
+    }
+  }
+}
+
+bool HWCSession::IsDisplayYUV(int disp) {
+  int error = -EINVAL;
+  bool is_yuv = false;
+  DisplayConfigVariableInfo attributes = {};
+
+  if (disp < 0 || disp >= HWC_NUM_DISPLAY_TYPES || !hwc_display_[disp]) {
+    DLOGE("Invalid input parameters. Display = %d", disp);
+    return is_yuv;
+  }
+
+  uint32_t active_config = 0;
+  error = hwc_display_[disp]->GetActiveDisplayConfig(&active_config);
+  if (!error) {
+    error = hwc_display_[disp]->GetDisplayAttributesForConfig(INT(active_config), &attributes);
+    if (error == 0) {
+      is_yuv = attributes.is_yuv;
+    } else {
+      DLOGW("Error querying display attributes. Display = %d, Config = %d", disp, active_config);
+    }
+  }
+
+  return is_yuv;
+}
+
+int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) {
+  SCOPE_LOCK(locker_);
+
+  if (!device) {
+    return -EINVAL;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  int status = -EINVAL;
+  if (hwc_session->hwc_display_[disp]) {
+    status = hwc_session->hwc_display_[disp]->EventControl(event, enable);
+  }
+
+  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;
+  if (hwc_session->hwc_display_[disp]) {
+    status = hwc_session->hwc_display_[disp]->SetPowerMode(mode);
+  }
+
+  return status;
+}
+
+int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) {
+  SCOPE_LOCK(locker_);
+
+  if (!device || !value) {
+    return -EINVAL;
+  }
+
+  int status = 0;
+
+  switch (param) {
+  case HWC_BACKGROUND_LAYER_SUPPORTED:
+    value[0] = 1;
+    break;
+
+  default:
+    status = -EINVAL;
+  }
+
+  return status;
+}
+
+void HWCSession::RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs) {
+  SCOPE_LOCK(locker_);
+
+  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, UINT32(length));
+}
+
+int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
+                                  size_t *num_configs) {
+  SCOPE_LOCK(locker_);
+
+  if (!device || !configs || !num_configs) {
+    return -EINVAL;
+  }
+
+  if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+    return -EINVAL;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  int status = -EINVAL;
+  if (hwc_session->hwc_display_[disp]) {
+    status = hwc_session->hwc_display_[disp]->GetDisplayConfigs(configs, num_configs);
+  }
+
+  return status;
+}
+
+int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
+                                     const uint32_t *display_attributes, int32_t *values) {
+  SCOPE_LOCK(locker_);
+
+  if (!device || !display_attributes || !values) {
+    return -EINVAL;
+  }
+
+  if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+    return -EINVAL;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  int status = -EINVAL;
+  if (hwc_session->hwc_display_[disp]) {
+    status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, display_attributes,
+                                                                   values);
+  }
+
+  return status;
+}
+
+int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) {
+  SCOPE_LOCK(locker_);
+
+  if (!device) {
+    return -EINVAL;
+  }
+
+  if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+    return -EINVAL;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  int active_config = -1;
+  if (hwc_session->hwc_display_[disp]) {
+    active_config = hwc_session->hwc_display_[disp]->GetActiveConfig();
+  }
+
+  return active_config;
+}
+
+int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  if (!device) {
+    return -EINVAL;
+  }
+
+  if (disp < HWC_DISPLAY_PRIMARY || disp >  HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+    return -EINVAL;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  int status = -EINVAL;
+
+  if (hwc_session->hwc_display_[disp]) {
+    status = hwc_session->hwc_display_[disp]->SetActiveConfig(index);
+  }
+
+  return status;
+}
+
+int HWCSession::SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y) {
+  DTRACE_SCOPED();
+
+  SCOPE_LOCK(locker_);
+
+  if (!device || (disp < HWC_DISPLAY_PRIMARY) || (disp > HWC_DISPLAY_VIRTUAL)) {
+    return -EINVAL;
+  }
+
+  int status = -EINVAL;
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  if (hwc_session->hwc_display_[disp]) {
+    status = hwc_session->hwc_display_[disp]->SetCursorPosition(x, y);
+  }
+
+  return status;
+}
+
+int HWCSession::ConnectDisplay(int disp, hwc_display_contents_1_t *content_list) {
+  DLOGI("Display = %d", disp);
+
+  int status = 0;
+  uint32_t primary_width = 0;
+  uint32_t primary_height = 0;
+
+  hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
+
+  if (disp == HWC_DISPLAY_EXTERNAL) {
+    status = CreateExternalDisplay(disp, primary_width, primary_height, false);
+    connected_displays_[HWC_DISPLAY_EXTERNAL] = 1;
+  } else if (disp == HWC_DISPLAY_VIRTUAL) {
+    status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
+                                       content_list, &hwc_display_[disp]);
+    connected_displays_[HWC_DISPLAY_VIRTUAL] = 1;
+  } else {
+    DLOGE("Invalid display type");
+    return -1;
+  }
+
+  if (!status) {
+    hwc_display_[disp]->SetSecureDisplay(secure_display_active_, true);
+  }
+
+  return status;
+}
+
+int HWCSession::DisconnectDisplay(int disp) {
+  DLOGI("Display = %d", disp);
+
+  if (disp == HWC_DISPLAY_EXTERNAL) {
+    HWCDisplayExternal::Destroy(hwc_display_[disp]);
+    connected_displays_[HWC_DISPLAY_EXTERNAL] = 0;
+  } else if (disp == HWC_DISPLAY_VIRTUAL) {
+    HWCDisplayVirtual::Destroy(hwc_display_[disp]);
+    connected_displays_[HWC_DISPLAY_VIRTUAL] = 0;
+  } else {
+    DLOGE("Invalid display type");
+    return -1;
+  }
+
+  hwc_display_[disp] = NULL;
+
+  return 0;
+}
+
+static void PostRefresh(hwc_procs_t const *hwc_procs) {
+  hwc_procs->invalidate(hwc_procs);
+}
+
+void HWCSession::AsyncRefresh() {
+  future_ = std::async(PostRefresh, hwc_procs_);
+}
+
+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:
+    AsyncRefresh();
+    break;
+
+  case qService::IQService::SET_IDLE_TIMEOUT:
+    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+      uint32_t timeout = UINT32(input_parcel->readInt32());
+      hwc_display_[HWC_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, output_parcel);
+    break;
+
+  case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
+    status = ConfigureRefreshRate(input_parcel);
+    break;
+
+  case qService::IQService::SET_VIEW_FRAME:
+    break;
+
+  case qService::IQService::TOGGLE_SCREEN_UPDATES:
+    status = ToggleScreenUpdates(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::QDCM_SVC_CMDS:
+    status = QdcmCMDHandler(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED:
+    status = OnMinHdcpEncryptionLevelChange(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::CONTROL_PARTIAL_UPDATE:
+    status = ControlPartialUpdate(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::SET_ACTIVE_CONFIG:
+    status = HandleSetActiveDisplayConfig(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::GET_ACTIVE_CONFIG:
+    status = HandleGetActiveDisplayConfig(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::GET_CONFIG_COUNT:
+    status = HandleGetDisplayConfigCount(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
+    status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::GET_PANEL_BRIGHTNESS:
+    status = GetPanelBrightness(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::SET_PANEL_BRIGHTNESS:
+    status = SetPanelBrightness(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
+    status = GetVisibleDisplayRect(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::SET_CAMERA_STATUS:
+    status = SetDynamicBWForCamera(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::GET_BW_TRANSACTION_STATUS:
+    status = GetBWTransactionStatus(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
+    status = SetMixerResolution(input_parcel);
+    break;
+
+  case qService::IQService::GET_HDR_CAPABILITIES:
+    status = GetHdrCapabilities(input_parcel, output_parcel);
+    break;
+
+  default:
+    DLOGW("QService command = %d is not supported", command);
+    return -EINVAL;
+  }
+
+  return status;
+}
+
+android::status_t HWCSession::ToggleScreenUpdates(const android::Parcel *input_parcel,
+                                                  android::Parcel *output_parcel) {
+  int input = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+
+  if (hwc_display_[HWC_DISPLAY_PRIMARY] && (input <= 1) && (input >= 0)) {
+    error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(input == 1);
+    if (error != 0) {
+      DLOGE("Failed to toggle screen updates = %d. Error = %d", input, error);
+    }
+  }
+  output_parcel->writeInt32(error);
+
+  return error;
+}
+
+android::status_t HWCSession::SetPanelBrightness(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel) {
+  int level = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+
+  if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(level);
+    if (error != 0) {
+      DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
+    }
+  }
+  output_parcel->writeInt32(error);
+
+  return error;
+}
+
+android::status_t HWCSession::GetPanelBrightness(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel) {
+  int error = android::BAD_VALUE;
+  int ret = error;
+
+  if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(&ret);
+    if (error != 0) {
+      ret = error;
+      DLOGE("Failed to get the panel brightness. Error = %d", error);
+    }
+  }
+  output_parcel->writeInt32(ret);
+
+  return error;
+}
+
+android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel,
+                                                   android::Parcel *output_parcel) {
+  DisplayError error = kErrorNone;
+  int ret = 0;
+  uint32_t disp_id = UINT32(input_parcel->readInt32());
+  uint32_t enable = UINT32(input_parcel->readInt32());
+
+  if (disp_id != HWC_DISPLAY_PRIMARY) {
+    DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
+    ret = -EINVAL;
+    output_parcel->writeInt32(ret);
+    return ret;
+  }
+
+  if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    DLOGE("primary display object is not instantiated");
+    ret = -EINVAL;
+    output_parcel->writeInt32(ret);
+    return ret;
+  }
+
+  uint32_t pending = 0;
+  error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlPartialUpdate(enable, &pending);
+
+  if (error == kErrorNone) {
+    if (!pending) {
+      output_parcel->writeInt32(ret);
+      return ret;
+    }
+  } else if (error == kErrorNotSupported) {
+    output_parcel->writeInt32(ret);
+    return ret;
+  } else {
+    ret = -EINVAL;
+    output_parcel->writeInt32(ret);
+    return ret;
+  }
+
+  AsyncRefresh();
+
+  // Wait until partial update control is complete
+  ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
+
+  output_parcel->writeInt32(ret);
+
+  return ret;
+}
+
+android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
+                                                           android::Parcel *output_parcel) {
+  int config = input_parcel->readInt32();
+  int dpy = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+
+  if (dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;
+  }
+
+  if (hwc_display_[dpy]) {
+    error = hwc_display_[dpy]->SetActiveDisplayConfig(config);
+    if (error == 0) {
+      AsyncRefresh();
+    }
+  }
+
+  return error;
+}
+
+android::status_t HWCSession::HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
+                                                           android::Parcel *output_parcel) {
+  int dpy = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+
+  if (dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;
+  }
+
+  if (hwc_display_[dpy]) {
+    uint32_t config = 0;
+    error = hwc_display_[dpy]->GetActiveDisplayConfig(&config);
+    if (error == 0) {
+      output_parcel->writeInt32(INT(config));
+    }
+  }
+
+  return error;
+}
+
+android::status_t HWCSession::HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
+                                                          android::Parcel *output_parcel) {
+  int dpy = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+
+  if (dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;
+  }
+
+  uint32_t count = 0;
+  if (hwc_display_[dpy]) {
+    error = hwc_display_[dpy]->GetDisplayConfigCount(&count);
+    if (error == 0) {
+      output_parcel->writeInt32(INT(count));
+    }
+  }
+
+  return error;
+}
+
+android::status_t HWCSession::SetDisplayPort(DisplayPort sdm_disp_port, int *hwc_disp_port) {
+  if (!hwc_disp_port) {
+    return -EINVAL;
+  }
+
+  switch (sdm_disp_port) {
+    case kPortDSI:
+      *hwc_disp_port = qdutils::DISPLAY_PORT_DSI;
+      break;
+    case kPortDTV:
+      *hwc_disp_port = qdutils::DISPLAY_PORT_DTV;
+      break;
+    case kPortLVDS:
+      *hwc_disp_port = qdutils::DISPLAY_PORT_LVDS;
+      break;
+    case kPortEDP:
+      *hwc_disp_port = qdutils::DISPLAY_PORT_EDP;
+      break;
+    case kPortWriteBack:
+      *hwc_disp_port = qdutils::DISPLAY_PORT_WRITEBACK;
+      break;
+    case kPortDP:
+      *hwc_disp_port = qdutils::DISPLAY_PORT_DP;
+      break;
+    case kPortDefault:
+      *hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT;
+      break;
+    default:
+      DLOGE("Invalid sdm display port %d", sdm_disp_port);
+      return -EINVAL;
+  }
+
+  return 0;
+}
+
+android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
+                                                                  *input_parcel,
+                                                                  android::Parcel *output_parcel) {
+  int config = input_parcel->readInt32();
+  int dpy = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+  DisplayConfigVariableInfo display_attributes;
+  DisplayPort sdm_disp_port = kPortDefault;
+  int hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT;
+
+  if (dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;
+  }
+
+  if (hwc_display_[dpy]) {
+    error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
+    if (error == 0) {
+      hwc_display_[dpy]->GetDisplayPort(&sdm_disp_port);
+
+      SetDisplayPort(sdm_disp_port, &hwc_disp_port);
+
+      output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
+      output_parcel->writeInt32(INT(display_attributes.x_pixels));
+      output_parcel->writeInt32(INT(display_attributes.y_pixels));
+      output_parcel->writeFloat(display_attributes.x_dpi);
+      output_parcel->writeFloat(display_attributes.y_dpi);
+      output_parcel->writeInt32(hwc_disp_port);
+      output_parcel->writeInt32(display_attributes.is_yuv);
+    }
+  }
+
+  return error;
+}
+
+android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
+                                                        android::Parcel *output_parcel) {
+  int ret = -EINVAL;
+
+  uint32_t display_id = UINT32(input_parcel->readInt32());
+  uint32_t display_status = UINT32(input_parcel->readInt32());
+
+  DLOGI("Display = %d, Status = %d", display_id, display_status);
+
+  if (display_id >= HWC_NUM_DISPLAY_TYPES) {
+    DLOGE("Invalid display_id");
+  } else if (display_id == HWC_DISPLAY_PRIMARY) {
+    DLOGE("Not supported for this display");
+  } else if (!hwc_display_[display_id]) {
+    DLOGW("Display is not connected");
+  } else {
+    ret = hwc_display_[display_id]->SetDisplayStatus(display_status);
+  }
+
+  output_parcel->writeInt32(ret);
+
+  return ret;
+}
+
+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:
+      return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
+          HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
+    case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
+      return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
+          HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
+    case qdutils::SET_BINDER_DYN_REFRESH_RATE:
+      {
+        uint32_t refresh_rate = UINT32(input_parcel->readInt32());
+        return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
+            HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE,
+            refresh_rate);
+      }
+    default:
+      DLOGW("Invalid operation %d", operation);
+      return -EINVAL;
+  }
+
+  return 0;
+}
+
+android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
+  uint32_t mode = UINT32(input_parcel->readInt32());
+  return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
+}
+
+android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
+  DisplayError error = kErrorNone;
+  std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
+  uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
+
+  if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
+    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+      error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+    }
+  }
+
+  if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
+    if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+      error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+    }
+  }
+
+  if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
+    if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+      error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+    }
+  }
+
+  return 0;
+}
+
+android::status_t HWCSession::SetDynamicBWForCamera(const android::Parcel *input_parcel,
+                                                    android::Parcel *output_parcel) {
+  DisplayError error = kErrorNone;
+  uint32_t camera_status = UINT32(input_parcel->readInt32());
+  HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault;
+
+  // trigger invalidate to apply new bw caps.
+  AsyncRefresh();
+
+    error = core_intf_->SetMaxBandwidthMode(mode);
+  if (error != kErrorNone) {
+      return -EINVAL;
+  }
+
+  new_bw_mode_ = true;
+  need_invalidate_ = true;
+
+  return 0;
+}
+
+android::status_t HWCSession::GetBWTransactionStatus(const android::Parcel *input_parcel,
+                                                     android::Parcel *output_parcel)  {
+  bool state = true;
+
+  if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    if (sync_wait(bw_mode_release_fd_, 0) < 0) {
+      DLOGI("bw_transaction_release_fd is not yet signalled: err= %s", strerror(errno));
+      state = false;
+    }
+    output_parcel->writeInt32(state);
+  }
+
+  return 0;
+}
+
+void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
+  uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
+  std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
+  uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
+
+  if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
+    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+      hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+
+  if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
+    if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+      hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+
+  if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
+    if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+      hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+}
+
+android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
+  DisplayError error = kErrorNone;
+  uint32_t dpy = UINT32(input_parcel->readInt32());
+
+  if (dpy != HWC_DISPLAY_PRIMARY) {
+    DLOGI("Resoulution change not supported for this display %d", dpy);
+    return -EINVAL;
+  }
+
+  if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    DLOGI("Primary display is not initialized");
+    return -EINVAL;
+  }
+
+  uint32_t width = UINT32(input_parcel->readInt32());
+  uint32_t height = UINT32(input_parcel->readInt32());
+
+  error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
+  if (error != kErrorNone) {
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
+android::status_t HWCSession::GetHdrCapabilities(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel) {
+  uint32_t display_id = UINT32(input_parcel->readInt32());
+  if (display_id >= HWC_NUM_DISPLAY_TYPES) {
+    DLOGE("Invalid display id = %d", display_id);
+    return -EINVAL;
+  }
+
+  if (hwc_display_[display_id] == NULL) {
+    DLOGW("Display = %d not initialized", display_id);
+    return -EINVAL;
+  }
+
+  DisplayConfigFixedInfo fixed_info = {};
+  int ret = hwc_display_[display_id]->GetDisplayFixedConfig(&fixed_info);
+  if (ret) {
+    DLOGE("Failed");
+    return ret;
+  }
+
+  if (!fixed_info.hdr_supported) {
+    DLOGI("HDR is not supported");
+    return 0;
+  }
+
+  std::vector<int32_t> supported_hdr_types;
+  // Only HDR10 supported now, in future add other supported HDR formats(HLG, DolbyVision)
+  supported_hdr_types.push_back(HAL_HDR_HDR10);
+
+  static const float kLuminanceFactor = 10000.0;
+  // luminance is expressed in the unit of 0.0001 cd/m2, convert it to 1cd/m2.
+  float max_luminance = FLOAT(fixed_info.max_luminance)/kLuminanceFactor;
+  float max_average_luminance = FLOAT(fixed_info.average_luminance)/kLuminanceFactor;
+  float min_luminance = FLOAT(fixed_info.min_luminance)/kLuminanceFactor;
+
+  if (output_parcel != nullptr) {
+    output_parcel->writeInt32Vector(supported_hdr_types);
+    output_parcel->writeFloat(max_luminance);
+    output_parcel->writeFloat(max_average_luminance);
+    output_parcel->writeFloat(min_luminance);
+  }
+
+  return 0;
+}
+
+void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
+  int type = input_parcel->readInt32();
+  bool enable = (input_parcel->readInt32() > 0);
+  DLOGI("type = %d enable = %d", type, enable);
+  int verbose_level = input_parcel->readInt32();
+
+  switch (type) {
+  case qService::IQService::DEBUG_ALL:
+    HWCDebugHandler::DebugAll(enable, verbose_level);
+    break;
+
+  case qService::IQService::DEBUG_MDPCOMP:
+    HWCDebugHandler::DebugStrategy(enable, verbose_level);
+    HWCDebugHandler::DebugCompManager(enable, verbose_level);
+    break;
+
+  case qService::IQService::DEBUG_PIPE_LIFECYCLE:
+    HWCDebugHandler::DebugResources(enable, verbose_level);
+    break;
+
+  case qService::IQService::DEBUG_DRIVER_CONFIG:
+    HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
+    break;
+
+  case qService::IQService::DEBUG_ROTATOR:
+    HWCDebugHandler::DebugResources(enable, verbose_level);
+    HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
+    HWCDebugHandler::DebugRotator(enable, verbose_level);
+    break;
+
+  case qService::IQService::DEBUG_QDCM:
+    HWCDebugHandler::DebugQdcm(enable, verbose_level);
+    break;
+
+  default:
+    DLOGW("type = %d is not supported", type);
+  }
+}
+
+android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
+                                             android::Parcel *output_parcel) {
+  int ret = 0;
+  int32_t *brightness_value = NULL;
+  uint32_t display_id(0);
+  PPPendingParams pending_action;
+  PPDisplayAPIPayload resp_payload, req_payload;
+
+  if (!color_mgr_) {
+    return -1;
+  }
+
+  pending_action.action = kNoAction;
+  pending_action.params = NULL;
+
+  // Read display_id, payload_size and payload from in_parcel.
+  ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
+  if (!ret) {
+    if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY])
+      ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload,
+                                                                  &resp_payload, &pending_action);
+
+    if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL])
+      ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload,
+                                                                  &pending_action);
+  }
+
+  if (ret) {
+    output_parcel->writeInt32(ret);  // first field in out parcel indicates return code.
+    req_payload.DestroyPayload();
+    resp_payload.DestroyPayload();
+    return ret;
+  }
+
+  switch (pending_action.action) {
+    case kInvalidating:
+      AsyncRefresh();
+      break;
+    case kEnterQDCMMode:
+      ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+      break;
+    case kExitQDCMMode:
+      ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+      break;
+    case kApplySolidFill:
+      ret = color_mgr_->SetSolidFill(pending_action.params,
+                                     true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+      AsyncRefresh();
+      break;
+    case kDisableSolidFill:
+      ret = color_mgr_->SetSolidFill(pending_action.params,
+                                     false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+      AsyncRefresh();
+      break;
+    case kSetPanelBrightness:
+      brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
+      if (brightness_value == NULL) {
+        DLOGE("Brightness value is Null");
+        return -EINVAL;
+      }
+      if (HWC_DISPLAY_PRIMARY == display_id)
+        ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
+      break;
+    case kEnableFrameCapture:
+      ret = color_mgr_->SetFrameCapture(pending_action.params,
+                                        true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+      AsyncRefresh();
+      break;
+    case kDisableFrameCapture:
+      ret = color_mgr_->SetFrameCapture(pending_action.params,
+                                        false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+      break;
+    case kConfigureDetailedEnhancer:
+      ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
+                                            hwc_display_[HWC_DISPLAY_PRIMARY]);
+      AsyncRefresh();
+      break;
+    case kInvalidatingAndkSetPanelBrightness:
+      brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
+      if (brightness_value == NULL) {
+        DLOGE("Brightness value is Null");
+        return -EINVAL;
+      }
+      if (HWC_DISPLAY_PRIMARY == display_id)
+        ret = hwc_display_[HWC_DISPLAY_PRIMARY]->CachePanelBrightness(*brightness_value);
+      AsyncRefresh();
+      break;
+    case kNoAction:
+      break;
+    default:
+      DLOGW("Invalid pending action = %d!", pending_action.action);
+      break;
+  }
+
+  // for display API getter case, marshall returned params into out_parcel.
+  output_parcel->writeInt32(ret);
+  HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
+  req_payload.DestroyPayload();
+  resp_payload.DestroyPayload();
+
+  return (ret? -EINVAL : 0);
+}
+
+android::status_t HWCSession::OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
+                                                             android::Parcel *output_parcel) {
+  int ret = -EINVAL;
+  uint32_t display_id = UINT32(input_parcel->readInt32());
+  uint32_t min_enc_level = UINT32(input_parcel->readInt32());
+
+  DLOGI("Display %d", display_id);
+
+  if (display_id >= HWC_NUM_DISPLAY_TYPES) {
+    DLOGE("Invalid display_id");
+  } else if (display_id != HWC_DISPLAY_EXTERNAL) {
+    DLOGE("Not supported for display");
+  } else if (!hwc_display_[display_id]) {
+    DLOGW("Display is not connected");
+  } else {
+    ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange(min_enc_level);
+  }
+
+  output_parcel->writeInt32(ret);
+
+  return ret;
+}
+
+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;
+
+  uevent_locker_.Lock();
+  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);
+    uevent_locker_.Signal();
+    uevent_locker_.Unlock();
+    return NULL;
+  }
+
+  uevent_locker_.Signal();
+  uevent_locker_.Unlock();
+
+  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;
+          AsyncRefresh();
+        } 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)) {
+    const 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 = hwc_display_[HWC_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");
+  int32_t mode = INT(hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode());
+  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode);
+  if (status) {
+    DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
+  }
+
+  status = hwc_display_[HWC_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) {
+  int status = 0;
+  bool notify_hotplug = false;
+  bool refresh_screen = false;
+
+  // To prevent sending events to client while a lock is held, acquire scope locks only within
+  // below scope so that those get automatically unlocked after the scope ends.
+  {
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+    if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+      DLOGE("Primay display is not connected.");
+      return -1;
+    }
+
+
+    HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
+    HWCDisplay *external_display = NULL;
+    HWCDisplay *null_display = NULL;
+
+    if (primary_display->GetDisplayClass() == DISPLAY_CLASS_EXTERNAL) {
+      external_display = static_cast<HWCDisplayExternal *>(hwc_display_[HWC_DISPLAY_PRIMARY]);
+    } else if (primary_display->GetDisplayClass() == DISPLAY_CLASS_NULL) {
+      null_display = static_cast<HWCDisplayNull *>(hwc_display_[HWC_DISPLAY_PRIMARY]);
+    }
+
+    // If primary display connected is a NULL display, then replace it with the external display
+    if (connected) {
+      // If we are in HDMI as primary and the primary display just got plugged in
+      if (is_hdmi_primary_ && null_display) {
+        uint32_t primary_width, primary_height;
+        int status = 0;
+        null_display->GetFrameBufferResolution(&primary_width, &primary_height);
+        delete null_display;
+        hwc_display_[HWC_DISPLAY_PRIMARY] = NULL;
+
+        // Create external display with a forced framebuffer resolution to that of what the NULL
+        // display had. This is necessary because SurfaceFlinger does not dynamically update
+        // framebuffer resolution once it reads it at bootup. So we always have to have the NULL
+        // display/external display both at the bootup resolution.
+        status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, primary_width, primary_height, true);
+        if (status) {
+          DLOGE("Could not create external display");
+          return -1;
+        }
+
+        status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_NORMAL);
+        if (status) {
+          DLOGE("power-on on primary failed with error = %d", status);
+        }
+
+        is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY);
+
+        // Next, go ahead and enable vsync on external display. This is expliclity required
+        // because in HDMI as primary case, SurfaceFlinger may not be aware of underlying
+        // changing display. and thus may not explicitly enable vsync
+
+        status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, true);
+        if (status) {
+          DLOGE("Error enabling vsync for HDMI as primary case");
+        }
+        // Don't do hotplug notification for HDMI as primary case for now
+        notify_hotplug = false;
+        refresh_screen = true;
+      } else {
+        if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+          DLOGE("HDMI is already connected");
+          return -1;
+        }
+
+        // Connect external display if virtual display is not connected.
+        // Else, defer external display connection and process it when virtual display
+        // tears down; Do not notify SurfaceFlinger since connection is deferred now.
+        if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+          status = ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL);
+          if (status) {
+            return status;
+          }
+          notify_hotplug = true;
+        } else {
+          DLOGI("Virtual display is connected, pending connection");
+          external_pending_connect_ = true;
+        }
+      }
+    } else {
+      // Do not return error if external display is not in connected status.
+      // Due to virtual display concurrency, external display connection might be still pending
+      // but hdmi got disconnected before pending connection could be processed.
+
+      if (is_hdmi_primary_ && external_display) {
+        uint32_t x_res, y_res;
+        external_display->GetFrameBufferResolution(&x_res, &y_res);
+        // Need to manually disable VSYNC as SF is not aware of connect/disconnect cases
+        // for HDMI as primary
+        external_display->EventControl(HWC_EVENT_VSYNC, false);
+        HWCDisplayExternal::Destroy(external_display);
+
+        HWCDisplayNull *null_display;
+
+        int status = HWCDisplayNull::Create(core_intf_, &hwc_procs_,
+                                            reinterpret_cast<HWCDisplay **>(&null_display));
+
+        if (status) {
+          DLOGE("Could not create Null display when primary got disconnected");
+          return -1;
+        }
+
+        null_display->SetResolution(x_res, y_res);
+        hwc_display_[HWC_DISPLAY_PRIMARY] = null_display;
+
+        // Don't do hotplug notification for HDMI as primary case for now
+        notify_hotplug = false;
+      } else {
+        if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+          status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
+          notify_hotplug = true;
+        }
+        external_pending_connect_ = false;
+      }
+    }
+  }
+
+  if (connected && (notify_hotplug || refresh_screen)) {
+    // trigger screen refresh to ensure sufficient resources are available to process new
+    // new display connection.
+    hwc_procs_->invalidate(hwc_procs_);
+    uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
+    usleep(vsync_period * 2 / 1000);
+  }
+  // notify client
+  if (notify_hotplug) {
+    hwc_procs_->hotplug(hwc_procs_, HWC_DISPLAY_EXTERNAL, connected);
+  }
+
+  qservice_->onHdmiHotplug(INT(connected));
+
+  return 0;
+}
+
+void HWCSession::HandleSecureDisplaySession(hwc_display_contents_1_t **displays) {
+  secure_display_active_ = false;
+  if (!*displays) {
+    DLOGW("Invalid display contents");
+    return;
+  }
+
+  hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY];
+  if (!content_list) {
+    DLOGW("Invalid primary content list");
+    return;
+  }
+  size_t num_hw_layers = content_list->numHwLayers;
+
+  for (size_t i = 0; i < num_hw_layers - 1; 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 (pvt_handle && pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
+      secure_display_active_ = true;
+    }
+  }
+
+  // Force flush on primary during transitions(secure<->non secure)
+  // when external displays are connected.
+  bool force_flush = false;
+  if ((connected_displays_[HWC_DISPLAY_PRIMARY] == 1) &&
+     ((connected_displays_[HWC_DISPLAY_EXTERNAL] == 1) ||
+      (connected_displays_[HWC_DISPLAY_VIRTUAL] == 1))) {
+    force_flush = true;
+  }
+
+  for (ssize_t dpy = static_cast<ssize_t>(HWC_NUM_DISPLAY_TYPES - 1); dpy >= 0; dpy--) {
+    if (hwc_display_[dpy]) {
+      hwc_display_[dpy]->SetSecureDisplay(secure_display_active_, force_flush);
+    }
+  }
+}
+
+android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
+                                                    android::Parcel *output_parcel) {
+  int dpy = input_parcel->readInt32();
+
+  if (dpy < HWC_DISPLAY_PRIMARY || dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;;
+  }
+
+  if (!hwc_display_[dpy]) {
+    return android::NO_INIT;
+  }
+
+  hwc_rect_t visible_rect = {0, 0, 0, 0};
+  int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
+  if (error < 0) {
+    return error;
+  }
+
+  output_parcel->writeInt32(visible_rect.left);
+  output_parcel->writeInt32(visible_rect.top);
+  output_parcel->writeInt32(visible_rect.right);
+  output_parcel->writeInt32(visible_rect.bottom);
+
+  return android::NO_ERROR;
+}
+
+int HWCSession::CreateExternalDisplay(int disp, uint32_t primary_width, uint32_t primary_height,
+                                      bool use_primary_res) {
+  uint32_t panel_bpp = 0;
+  uint32_t pattern_type = 0;
+
+  if (qdutils::isDPConnected()) {
+    qdutils::getDPTestConfig(&panel_bpp, &pattern_type);
+  }
+
+  if (panel_bpp && pattern_type) {
+    return HWCDisplayExternalTest::Create(core_intf_, &hwc_procs_, qservice_, panel_bpp,
+                                          pattern_type, &hwc_display_[disp]);
+  }
+
+  return HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
+                                    qservice_, use_primary_res, &hwc_display_[disp]);
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/hwc/hwc_session.h b/sdm845/sdm/libs/hwc/hwc_session.h
new file mode 100644
index 0000000..ce21c46
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_session.h
@@ -0,0 +1,166 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <future>   // NOLINT
+
+#include "hwc_display_primary.h"
+#include "hwc_display_external.h"
+#include "hwc_display_virtual.h"
+#include "hwc_color_manager.h"
+#include "hwc_socket_handler.h"
+
+namespace sdm {
+
+class HWCSession : hwc_composer_device_1_t, 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;
+  static const int kPartialUpdateControlTimeoutMs = 100;
+
+  // 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);
+  // These config functions always return FB params, the actual display params may differ.
+  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 *display_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);
+  static int SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y);
+  static void CloseAcquireFds(hwc_display_contents_1_t *content_list);
+  bool IsDisplayYUV(int disp);
+
+  // 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();
+  int ConnectDisplay(int disp, hwc_display_contents_1_t *content_list);
+  int DisconnectDisplay(int disp);
+  void HandleSecureDisplaySession(hwc_display_contents_1_t **displays);
+  int GetVsyncPeriod(int disp);
+  int CreateExternalDisplay(int disp, uint32_t primary_width, uint32_t primary_height,
+                            bool use_primary_res);
+  void AsyncRefresh();
+
+  // 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,
+                                              android::Parcel *output_parcel);
+  android::status_t ToggleScreenUpdates(const android::Parcel *input_parcel,
+                                        android::Parcel *output_parcel);
+  android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
+  android::status_t QdcmCMDHandler(const android::Parcel *input_parcel,
+                                   android::Parcel *output_parcel);
+  android::status_t ControlPartialUpdate(const android::Parcel *input_parcel,
+                                         android::Parcel *output_parcel);
+  android::status_t OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
+                                                   android::Parcel *output_parcel);
+  android::status_t SetPanelBrightness(const android::Parcel *input_parcel,
+                                       android::Parcel *output_parcel);
+  android::status_t GetPanelBrightness(const android::Parcel *input_parcel,
+                                       android::Parcel *output_parcel);
+  // These functions return the actual display config info as opposed to FB
+  android::status_t HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel);
+  android::status_t HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel);
+  android::status_t HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
+                                                android::Parcel *output_parcel);
+  android::status_t HandleGetDisplayAttributesForConfig(const android::Parcel *input_parcel,
+                                                        android::Parcel *output_parcel);
+  android::status_t GetVisibleDisplayRect(const android::Parcel *input_parcel,
+                                          android::Parcel *output_parcel);
+
+  android::status_t SetDynamicBWForCamera(const android::Parcel *input_parcel,
+                                          android::Parcel *output_parcel);
+  android::status_t GetBWTransactionStatus(const android::Parcel *input_parcel,
+                                          android::Parcel *output_parcel);
+  android::status_t SetMixerResolution(const android::Parcel *input_parcel);
+  android::status_t SetDisplayPort(DisplayPort sdm_disp_port, int *hwc_disp_port);
+  android::status_t GetHdrCapabilities(const android::Parcel *input_parcel,
+                                       android::Parcel *output_parcel);
+
+  static Locker locker_;
+  CoreInterface *core_intf_ = NULL;
+  hwc_procs_t hwc_procs_default_;
+  hwc_procs_t const *hwc_procs_ = &hwc_procs_default_;
+  HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = { NULL };
+  pthread_t uevent_thread_;
+  bool uevent_thread_exit_ = false;
+  const char *uevent_thread_name_ = "HWC_UeventThread";
+  HWCBufferAllocator buffer_allocator_;
+  HWCBufferSyncHandler buffer_sync_handler_;
+  HWCColorManager *color_mgr_ = NULL;
+  bool reset_panel_ = false;
+  bool secure_display_active_ = false;
+  bool external_pending_connect_ = false;
+  bool new_bw_mode_ = false;
+  bool need_invalidate_ = false;
+  int bw_mode_release_fd_ = -1;
+  qService::QService *qservice_ = NULL;
+  bool is_hdmi_primary_ = false;
+  bool is_hdmi_yuv_ = false;
+  std::future<void> future_;
+  std::bitset<HWC_NUM_DISPLAY_TYPES> connected_displays_;  // Bit mask of connected displays
+  HWCSocketHandler socket_handler_;
+  Locker uevent_locker_;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_SESSION_H__
+
diff --git a/sdm845/sdm/libs/hwc/hwc_socket_handler.cpp b/sdm845/sdm/libs/hwc/hwc_socket_handler.cpp
new file mode 100644
index 0000000..7ebaab4
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_socket_handler.cpp
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*  * Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above
+*    copyright notice, this list of conditions and the following
+*    disclaimer in the documentation and/or other materials provided
+*    with the distribution.
+*  * Neither the name of The Linux Foundation nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cutils/sockets.h>
+#include "hwc_socket_handler.h"
+
+#define __CLASS__ "HWCSocketHandler"
+
+#define DPPS_SOCKET "pps"
+
+namespace sdm {
+
+int HWCSocketHandler::GetSocketFd(SocketType socket_type) {
+  switch (socket_type) {
+  case kDpps:
+    return socket_local_client(DPPS_SOCKET, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+  default:
+    return -1;
+  }
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc/hwc_socket_handler.h b/sdm845/sdm/libs/hwc/hwc_socket_handler.h
new file mode 100644
index 0000000..5b2292a
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_socket_handler.h
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*  * Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above
+*    copyright notice, this list of conditions and the following
+*    disclaimer in the documentation and/or other materials provided
+*    with the distribution.
+*  * Neither the name of The Linux Foundation nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef __HWC_SOCKET_HANDLER_H__
+#define __HWC_SOCKET_HANDLER_H__
+
+#include <core/socket_handler.h>
+
+namespace sdm {
+
+class HWCSocketHandler : public SocketHandler {
+ public:
+  HWCSocketHandler() { }
+
+  virtual int GetSocketFd(SocketType socket_type);
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_SOCKET_HANDLER_H__
diff --git a/sdm845/sdm/libs/hwc/hwc_tonemapper.cpp b/sdm845/sdm/libs/hwc/hwc_tonemapper.cpp
new file mode 100644
index 0000000..c09ff9e
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_tonemapper.cpp
@@ -0,0 +1,341 @@
+/*
+* Copyright (c) 2016 - 2017, 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 <alloc_controller.h>
+#include <gr.h>
+#include <gralloc_priv.h>
+#include <memalloc.h>
+#include <sync/sync.h>
+
+#include <TonemapFactory.h>
+
+#include <core/buffer_allocator.h>
+
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/formats.h>
+#include <utils/rect.h>
+#include <utils/utils.h>
+
+#include <vector>
+
+#include "hwc_debugger.h"
+#include "hwc_tonemapper.h"
+
+#define __CLASS__ "HWCToneMapper"
+
+namespace sdm {
+
+ToneMapSession::~ToneMapSession() {
+  delete gpu_tone_mapper_;
+  gpu_tone_mapper_ = NULL;
+  FreeIntermediateBuffers();
+}
+
+DisplayError ToneMapSession::AllocateIntermediateBuffers(int w, int h, int format, int usage) {
+  for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
+    int status = alloc_buffer(&intermediate_buffer_[i], w, h, format, usage);
+    if (status < 0) {
+      FreeIntermediateBuffers();
+      return kErrorMemory;
+    }
+  }
+
+  return kErrorNone;
+}
+
+void ToneMapSession::FreeIntermediateBuffers() {
+  for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
+    private_handle_t *buffer = intermediate_buffer_[i];
+    if (buffer) {
+      // Free the valid fence
+      if (release_fence_fd_[i] >= 0) {
+        CloseFd(&release_fence_fd_[i]);
+      }
+      free_buffer(buffer);
+      intermediate_buffer_[i] = NULL;
+    }
+  }
+}
+
+void ToneMapSession::UpdateBuffer(int acquire_fence, LayerBuffer *buffer) {
+  // Acquire fence will be closed by HWC Display.
+  // Fence returned by GPU will be closed in PostCommit.
+  buffer->acquire_fence_fd = acquire_fence;
+  buffer->size = intermediate_buffer_[current_buffer_index_]->size;
+  buffer->planes[0].fd = intermediate_buffer_[current_buffer_index_]->fd;
+}
+
+void ToneMapSession::SetReleaseFence(int fd) {
+  CloseFd(&release_fence_fd_[current_buffer_index_]);
+  // Used to give to GPU tonemapper along with input layer fd
+  release_fence_fd_[current_buffer_index_] = dup(fd);
+}
+
+void ToneMapSession::SetToneMapConfig(Layer *layer) {
+  // HDR -> SDR is FORWARD and SDR - > HDR is INVERSE
+  tone_map_config_.type = layer->input_buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
+  tone_map_config_.colorPrimaries = layer->input_buffer.color_metadata.colorPrimaries;
+  tone_map_config_.transfer = layer->input_buffer.color_metadata.transfer;
+  tone_map_config_.secure = layer->request.flags.secure;
+  tone_map_config_.format = layer->request.format;
+}
+
+bool ToneMapSession::IsSameToneMapConfig(Layer *layer) {
+  LayerBuffer& buffer = layer->input_buffer;
+  private_handle_t *handle = intermediate_buffer_[0];
+  int tonemap_type = buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
+
+  return ((tonemap_type == tone_map_config_.type) &&
+          (buffer.color_metadata.colorPrimaries == tone_map_config_.colorPrimaries) &&
+          (buffer.color_metadata.transfer == tone_map_config_.transfer) &&
+          (layer->request.flags.secure == tone_map_config_.secure) &&
+          (layer->request.format == tone_map_config_.format) &&
+          (layer->request.width == UINT32(handle->unaligned_width)) &&
+          (layer->request.height == UINT32(handle->unaligned_height)));
+}
+
+int HWCToneMapper::HandleToneMap(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) {
+  uint32_t gpu_count = 0;
+  DisplayError error = kErrorNone;
+
+  for (uint32_t i = 0; i < layer_stack->layers.size(); i++) {
+    uint32_t session_index = 0;
+    Layer *layer = layer_stack->layers.at(i);
+    if (layer->composition == kCompositionGPU) {
+      gpu_count++;
+    }
+
+    if (layer->request.flags.tone_map) {
+      switch (layer->composition) {
+      case kCompositionGPUTarget:
+        if (!gpu_count) {
+          // When all layers are on FrameBuffer and if they do not update in the next draw cycle,
+          // then SDM marks them for SDE Composition because the cached FB layer gets displayed.
+          // GPU count will be 0 in this case. Try to use the existing tone-mapped frame buffer.
+          // No ToneMap/Blit is required. Just update the buffer & acquire fence fd of FB layer.
+          if (!tone_map_sessions_.empty()) {
+            ToneMapSession *fb_tone_map_session = tone_map_sessions_.at(fb_session_index_);
+            fb_tone_map_session->UpdateBuffer(-1 /* acquire_fence */, &layer->input_buffer);
+            fb_tone_map_session->layer_index_ = INT(i);
+            fb_tone_map_session->acquired_ = true;
+            return 0;
+          }
+        }
+        error = AcquireToneMapSession(layer, &session_index);
+        fb_session_index_ = session_index;
+        break;
+      default:
+        error = AcquireToneMapSession(layer, &session_index);
+        break;
+      }
+
+      if (error != kErrorNone) {
+        Terminate();
+        return -1;
+      }
+
+      ToneMapSession *session = tone_map_sessions_.at(session_index);
+      ToneMap(&content_list->hwLayers[i], layer, session);
+      session->layer_index_ = INT(i);
+    }
+  }
+
+  return 0;
+}
+
+void HWCToneMapper::ToneMap(hwc_layer_1_t *hwc_layer, Layer* layer, ToneMapSession *session) {
+  int fence_fd = -1;
+  int acquire_fd = -1;
+  int merged_fd = -1;
+
+  uint8_t buffer_index = session->current_buffer_index_;
+  const private_handle_t *dst_hnd = session->intermediate_buffer_[buffer_index];
+  const private_handle_t *src_hnd = static_cast<const private_handle_t *>(hwc_layer->handle);
+
+  acquire_fd = dup(layer->input_buffer.acquire_fence_fd);
+  buffer_sync_handler_.SyncMerge(session->release_fence_fd_[buffer_index], acquire_fd, &merged_fd);
+
+  if (acquire_fd >= 0) {
+    CloseFd(&acquire_fd);
+  }
+
+  if (session->release_fence_fd_[buffer_index] >= 0) {
+    CloseFd(&session->release_fence_fd_[buffer_index]);
+  }
+
+  DTRACE_BEGIN("GPU_TM_BLIT");
+  fence_fd = session->gpu_tone_mapper_->blit(reinterpret_cast<const void *>(dst_hnd),
+                                             reinterpret_cast<const void *>(src_hnd), merged_fd);
+  DTRACE_END();
+
+  DumpToneMapOutput(session, &fence_fd);
+  session->UpdateBuffer(fence_fd, &layer->input_buffer);
+}
+
+void HWCToneMapper::PostCommit(LayerStack *layer_stack) {
+  auto it = tone_map_sessions_.begin();
+  while (it != tone_map_sessions_.end()) {
+    uint32_t session_index = UINT32(std::distance(tone_map_sessions_.begin(), it));
+    ToneMapSession *session = tone_map_sessions_.at(session_index);
+    Layer *layer = layer_stack->layers.at(UINT32(session->layer_index_));
+    if (session->acquired_) {
+      // Close the fd returned by GPU ToneMapper and set release fence.
+      LayerBuffer &layer_buffer = layer->input_buffer;
+      CloseFd(&layer_buffer.acquire_fence_fd);
+      session->SetReleaseFence(layer_buffer.release_fence_fd);
+      session->acquired_ = false;
+      it++;
+    } else {
+      delete session;
+      it = tone_map_sessions_.erase(it);
+    }
+  }
+}
+
+void HWCToneMapper::Terminate() {
+  if (tone_map_sessions_.size()) {
+    while (!tone_map_sessions_.empty()) {
+      delete tone_map_sessions_.back();
+      tone_map_sessions_.pop_back();
+    }
+    fb_session_index_ = 0;
+  }
+}
+
+void HWCToneMapper::SetFrameDumpConfig(uint32_t count) {
+  DLOGI("Dump FrameConfig count = %d", count);
+  dump_frame_count_ = count;
+  dump_frame_index_ = 0;
+}
+
+void HWCToneMapper::DumpToneMapOutput(ToneMapSession *session, int *acquire_fd) {
+  if (!dump_frame_count_) {
+    return;
+  }
+
+  private_handle_t *target_buffer = session->intermediate_buffer_[session->current_buffer_index_];
+
+  if (*acquire_fd >= 0) {
+    int error = sync_wait(*acquire_fd, 1000);
+    if (error < 0) {
+      DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+      return;
+    }
+  }
+
+  size_t result = 0;
+  char dump_file_name[PATH_MAX];
+  snprintf(dump_file_name, sizeof(dump_file_name), "/data/misc/display/frame_dump_primary"
+           "/tonemap_%dx%d_frame%d.raw", target_buffer->width, target_buffer->height,
+           dump_frame_index_);
+
+  FILE* fp = fopen(dump_file_name, "w+");
+  if (fp) {
+    DLOGI("base addr = %x", target_buffer->base);
+    result = fwrite(reinterpret_cast<void *>(target_buffer->base), target_buffer->size, 1, fp);
+    fclose(fp);
+  }
+  dump_frame_count_--;
+  dump_frame_index_++;
+  CloseFd(acquire_fd);
+}
+
+DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index) {
+  Color10Bit *grid_entries = NULL;
+  int grid_size = 0;
+
+  if (layer->lut_3d.validGridEntries) {
+    grid_entries = layer->lut_3d.gridEntries;
+    grid_size = INT(layer->lut_3d.gridSize);
+  }
+
+  // When the property sdm.disable_hdr_lut_gen is set, the lutEntries and gridEntries in
+  // the Lut3d will be NULL, clients needs to allocate the memory and set correct 3D Lut
+  // for Tonemapping.
+  if (!layer->lut_3d.lutEntries || !layer->lut_3d.dim) {
+    // Atleast lutEntries must be valid for GPU Tonemapper.
+    DLOGE("Invalid Lut Entries or lut dimension = %d", layer->lut_3d.dim);
+    return kErrorParameters;
+  }
+
+  // Check if we can re-use an existing tone map session.
+  for (uint32_t i = 0; i < tone_map_sessions_.size(); i++) {
+    ToneMapSession *tonemap_session = tone_map_sessions_.at(i);
+    if (!tonemap_session->acquired_ && tonemap_session->IsSameToneMapConfig(layer)) {
+      tonemap_session->current_buffer_index_ = (tonemap_session->current_buffer_index_ + 1) %
+                                                ToneMapSession::kNumIntermediateBuffers;
+      tonemap_session->acquired_ = true;
+      *session_index = i;
+      return kErrorNone;
+    }
+  }
+
+  ToneMapSession *session = new ToneMapSession();
+
+  session->SetToneMapConfig(layer);
+  session->gpu_tone_mapper_ = TonemapperFactory_GetInstance(session->tone_map_config_.type,
+                                                            layer->lut_3d.lutEntries,
+                                                            layer->lut_3d.dim,
+                                                            grid_entries, grid_size,
+                                                            session->tone_map_config_.secure);
+
+  if (session->gpu_tone_mapper_ == NULL) {
+    DLOGE("Get Tonemapper failed!");
+    delete session;
+    return kErrorNotSupported;
+  }
+
+  int status, format;
+  DisplayError error = kErrorNone;
+  int usage = INT(GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | GRALLOC_USAGE_HW_TEXTURE);
+
+  if (layer->request.flags.secure) {
+    usage = INT(GRALLOC_USAGE_PRIVATE_MM_HEAP);
+    usage |= INT(GRALLOC_USAGE_PROTECTED);
+  }
+
+  status = buffer_allocator_.SetBufferInfo(layer->request.format, &format, &usage);
+  error = session->AllocateIntermediateBuffers(INT(layer->request.width),
+                                               INT(layer->request.height), format, usage);
+
+  if (error != kErrorNone) {
+    DLOGE("Allocation of Intermediate Buffers failed!");
+    delete session;
+    return error;
+  }
+
+  session->acquired_ = true;
+  tone_map_sessions_.push_back(session);
+  *session_index = UINT32(tone_map_sessions_.size() - 1);
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc/hwc_tonemapper.h b/sdm845/sdm/libs/hwc/hwc_tonemapper.h
new file mode 100644
index 0000000..0a463fe
--- /dev/null
+++ b/sdm845/sdm/libs/hwc/hwc_tonemapper.h
@@ -0,0 +1,101 @@
+/*
+* Copyright (c) 2016 - 2017, 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_TONEMAPPER_H__
+#define __HWC_TONEMAPPER_H__
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include <hardware/hwcomposer.h>
+
+#include <core/layer_stack.h>
+#include <utils/sys.h>
+#include <vector>
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_buffer_allocator.h"
+
+class Tonemapper;
+
+namespace sdm {
+
+struct ToneMapConfig {
+  int type = 0;
+  ColorPrimaries colorPrimaries = ColorPrimaries_Max;
+  GammaTransfer transfer = Transfer_Max;
+  LayerBufferFormat format = kFormatRGBA8888;
+  bool secure = false;
+};
+
+class ToneMapSession {
+ public:
+  ~ToneMapSession();
+  DisplayError AllocateIntermediateBuffers(int width, int height, int format, int usage);
+  void FreeIntermediateBuffers();
+  void UpdateBuffer(int acquire_fence, LayerBuffer *buffer);
+  void SetReleaseFence(int fd);
+  void SetToneMapConfig(Layer *layer);
+  bool IsSameToneMapConfig(Layer *layer);
+
+  static const uint8_t kNumIntermediateBuffers = 2;
+  Tonemapper *gpu_tone_mapper_ = NULL;
+  ToneMapConfig tone_map_config_ = {};
+  uint8_t current_buffer_index_ = 0;
+  private_handle_t *intermediate_buffer_[kNumIntermediateBuffers] = {NULL, NULL};
+  int release_fence_fd_[kNumIntermediateBuffers] = {-1, -1};
+  bool acquired_ = false;
+  int layer_index_ = -1;
+};
+
+class HWCToneMapper {
+ public:
+  HWCToneMapper() {}
+  ~HWCToneMapper() {}
+
+  int HandleToneMap(hwc_display_contents_1_t *content_list, LayerStack *layer_stack);
+  bool IsActive() { return !tone_map_sessions_.empty(); }
+  void PostCommit(LayerStack *layer_stack);
+  void SetFrameDumpConfig(uint32_t count);
+  void Terminate();
+
+ private:
+  void ToneMap(hwc_layer_1_t *hwc_layer, Layer *layer, ToneMapSession *session);
+  DisplayError AcquireToneMapSession(Layer *layer, uint32_t *session_index);
+  void DumpToneMapOutput(ToneMapSession *session, int *acquire_fence);
+
+  std::vector<ToneMapSession*> tone_map_sessions_;
+  HWCBufferSyncHandler buffer_sync_handler_ = {};
+  HWCBufferAllocator buffer_allocator_ = {};
+  uint32_t dump_frame_count_ = 0;
+  uint32_t dump_frame_index_ = 0;
+  uint32_t fb_session_index_ = 0;
+};
+
+}  // namespace sdm
+#endif  // __HWC_TONEMAPPER_H__
diff --git a/sdm845/sdm/libs/hwc2/Android.mk b/sdm845/sdm/libs/hwc2/Android.mk
new file mode 100644
index 0000000..557b55f
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/Android.mk
@@ -0,0 +1,54 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/../../../common.mk
+
+ifeq ($(use_hwc2),true)
+
+LOCAL_MODULE                  := hwcomposer.$(TARGET_BOARD_PLATFORM)
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_RELATIVE_PATH    := hw
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes)
+LOCAL_HEADER_LIBRARIES        := display_headers
+
+LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
+                                 -std=c++11 -fcolor-diagnostics\
+                                 -DLOG_TAG=\"SDM\" $(common_flags) \
+                                 -I $(display_top)/sdm/libs/hwc
+LOCAL_CLANG                   := true
+
+LOCAL_SHARED_LIBRARIES        := libsdmcore libqservice libbinder libhardware libhardware_legacy \
+                                 libutils libcutils libsync libqdutils libqdMetaData libdl \
+                                 libpowermanager libsdmutils libc++ liblog libgrallocutils \
+                                 libui libgpu_tonemapper
+
+ifneq ($(TARGET_USES_GRALLOC1), true)
+    LOCAL_SHARED_LIBRARIES += libmemalloc
+endif
+
+LOCAL_SRC_FILES               := hwc_session.cpp \
+                                 hwc_display.cpp \
+                                 hwc_display_primary.cpp \
+                                 hwc_display_external.cpp \
+                                 hwc_display_virtual.cpp \
+                                 ../hwc/hwc_debugger.cpp \
+                                 ../hwc/hwc_buffer_sync_handler.cpp \
+                                 hwc_color_manager.cpp \
+                                 hwc_layers.cpp \
+                                 hwc_callbacks.cpp \
+                                 ../hwc/cpuhint.cpp \
+                                 ../hwc/hwc_socket_handler.cpp \
+                                 hwc_tonemapper.cpp
+
+ifneq ($(TARGET_USES_GRALLOC1), true)
+    LOCAL_SRC_FILES += ../hwc/hwc_buffer_allocator.cpp
+else
+    LOCAL_SRC_FILES += hwc_buffer_allocator.cpp
+endif
+
+ifeq ($(TARGET_HAS_WIDE_COLOR_DISPLAY), true)
+    LOCAL_CFLAGS += -DFEATURE_WIDE_COLOR
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+endif
diff --git a/sdm845/sdm/libs/hwc2/hwc_buffer_allocator.cpp b/sdm845/sdm/libs/hwc2/hwc_buffer_allocator.cpp
new file mode 100644
index 0000000..3c8d460
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_buffer_allocator.cpp
@@ -0,0 +1,357 @@
+/*
+* Copyright (c) 2015-2017, 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 <core/buffer_allocator.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+
+#include "hwc_buffer_allocator.h"
+#include "hwc_debugger.h"
+#include "gr_utils.h"
+
+#define __CLASS__ "HWCBufferAllocator"
+
+namespace sdm {
+
+HWCBufferAllocator::HWCBufferAllocator() {
+  int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module_);
+  if (err != 0) {
+    DLOGE("FATAL: can not open GRALLOC module");
+  } else {
+    gralloc1_open(module_, &gralloc_device_);
+  }
+  ReleaseBuffer_ = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
+      gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_RELEASE));
+  Perform_ = reinterpret_cast<GRALLOC1_PFN_PERFORM>(
+      gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_PERFORM));
+}
+
+HWCBufferAllocator::~HWCBufferAllocator() {
+  if (gralloc_device_ != nullptr) {
+    gralloc1_close(gralloc_device_);
+  }
+}
+
+DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
+  const BufferConfig &buffer_config = buffer_info->buffer_config;
+  AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
+  uint32_t width = buffer_config.width;
+  uint32_t height = buffer_config.height;
+  int format;
+  uint64_t alloc_flags = 0;
+  int error = SetBufferInfo(buffer_config.format, &format, &alloc_flags);
+  if (error != 0) {
+    return kErrorParameters;
+  }
+
+  if (buffer_config.secure) {
+    alloc_flags |= GRALLOC1_PRODUCER_USAGE_PROTECTED;
+  }
+
+  if (!buffer_config.cache) {
+    // Allocate uncached buffers
+    alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+  }
+
+  if (buffer_config.gfx_client) {
+    alloc_flags |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
+  }
+
+  uint64_t producer_usage = alloc_flags;
+  uint64_t consumer_usage = alloc_flags;
+  // CreateBuffer
+  private_handle_t *hnd = nullptr;
+  Perform_(gralloc_device_, GRALLOC1_MODULE_PERFORM_ALLOCATE_BUFFER, width, height, format,
+           producer_usage, consumer_usage, &hnd);
+
+  if (hnd) {
+    alloc_buffer_info->fd = hnd->fd;
+    alloc_buffer_info->stride = UINT32(hnd->width);
+    alloc_buffer_info->size = hnd->size;
+  } else {
+    DLOGE("Failed to allocate memory");
+    return kErrorMemory;
+  }
+
+  buffer_info->private_data = reinterpret_cast<void *>(hnd);
+  return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::FreeBuffer(BufferInfo *buffer_info) {
+  DisplayError err = kErrorNone;
+  buffer_handle_t hnd = static_cast<private_handle_t *>(buffer_info->private_data);
+  ReleaseBuffer_(gralloc_device_, hnd);
+  AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
+
+  alloc_buffer_info->fd = -1;
+  alloc_buffer_info->stride = 0;
+  alloc_buffer_info->size = 0;
+  buffer_info->private_data = NULL;
+  return err;
+}
+
+void HWCBufferAllocator::GetCustomWidthAndHeight(const private_handle_t *handle, int *width,
+                                                 int *height) {
+  Perform_(gralloc_device_, GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE, handle,
+           width, height);
+}
+
+void HWCBufferAllocator::GetAlignedWidthAndHeight(int width, int height, int format,
+                                                  uint32_t alloc_type, int *aligned_width,
+                                                  int *aligned_height) {
+  int tile_enabled;
+  gralloc1_producer_usage_t producer_usage = GRALLOC1_PRODUCER_USAGE_NONE;
+  gralloc1_consumer_usage_t consumer_usage = GRALLOC1_CONSUMER_USAGE_NONE;
+  if (alloc_type & GRALLOC_USAGE_HW_FB) {
+    consumer_usage = GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET;
+  }
+
+  Perform_(gralloc_device_, GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES, width, height, format,
+           producer_usage, consumer_usage, aligned_width, aligned_height, &tile_enabled);
+}
+
+uint32_t HWCBufferAllocator::GetBufferSize(BufferInfo *buffer_info) {
+  const BufferConfig &buffer_config = buffer_info->buffer_config;
+  uint64_t alloc_flags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
+
+  int width = INT(buffer_config.width);
+  int height = INT(buffer_config.height);
+  int format;
+
+  if (buffer_config.secure) {
+    alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
+  }
+
+  if (!buffer_config.cache) {
+    // Allocate uncached buffers
+    alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+  }
+
+  if (SetBufferInfo(buffer_config.format, &format, &alloc_flags) < 0) {
+    return 0;
+  }
+
+  uint32_t aligned_width = 0, aligned_height = 0, buffer_size = 0;
+  gralloc1_producer_usage_t producer_usage = GRALLOC1_PRODUCER_USAGE_NONE;
+  gralloc1_consumer_usage_t consumer_usage = GRALLOC1_CONSUMER_USAGE_NONE;
+  // TODO(user): Currently both flags are treated similarly in gralloc
+  producer_usage = gralloc1_producer_usage_t(alloc_flags);
+  consumer_usage = gralloc1_consumer_usage_t(alloc_flags);
+  gralloc1::BufferInfo info(width, height, format, producer_usage, consumer_usage);
+  GetBufferSizeAndDimensions(info, &buffer_size, &aligned_width, &aligned_height);
+  return buffer_size;
+}
+
+int HWCBufferAllocator::SetBufferInfo(LayerBufferFormat format, int *target, uint64_t *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 kFormatBGR565:
+      *target = HAL_PIXEL_FORMAT_BGR_565;
+      break;
+    case kFormatBGR888:
+      *target = HAL_PIXEL_FORMAT_BGR_888;
+      break;
+    case kFormatBGRA8888:
+      *target = HAL_PIXEL_FORMAT_BGRA_8888;
+      break;
+    case kFormatYCrCb420PlanarStride16:
+      *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 kFormatCbYCrY422H2V1Packed:
+      *target = HAL_PIXEL_FORMAT_CbYCrY_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 kFormatYCrCb420SemiPlanarVenus:
+      *target = HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS;
+      break;
+    case kFormatYCbCr420SPVenusUbwc:
+      *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+      *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+      break;
+    case kFormatRGBA5551:
+      *target = HAL_PIXEL_FORMAT_RGBA_5551;
+      break;
+    case kFormatRGBA4444:
+      *target = HAL_PIXEL_FORMAT_RGBA_4444;
+      break;
+    case kFormatRGBA1010102:
+      *target = HAL_PIXEL_FORMAT_RGBA_1010102;
+      break;
+    case kFormatARGB2101010:
+      *target = HAL_PIXEL_FORMAT_ARGB_2101010;
+      break;
+    case kFormatRGBX1010102:
+      *target = HAL_PIXEL_FORMAT_RGBX_1010102;
+      break;
+    case kFormatXRGB2101010:
+      *target = HAL_PIXEL_FORMAT_XRGB_2101010;
+      break;
+    case kFormatBGRA1010102:
+      *target = HAL_PIXEL_FORMAT_BGRA_1010102;
+      break;
+    case kFormatABGR2101010:
+      *target = HAL_PIXEL_FORMAT_ABGR_2101010;
+      break;
+    case kFormatBGRX1010102:
+      *target = HAL_PIXEL_FORMAT_BGRX_1010102;
+      break;
+    case kFormatXBGR2101010:
+      *target = HAL_PIXEL_FORMAT_XBGR_2101010;
+      break;
+    case kFormatYCbCr420P010:
+      *target = HAL_PIXEL_FORMAT_YCbCr_420_P010;
+      break;
+    case kFormatYCbCr420TP10Ubwc:
+      *target = HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC;
+      *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+      break;
+    case kFormatYCbCr420P010Ubwc:
+      *target = HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC;
+      *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+      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 kFormatBGR565Ubwc:
+      *target = HAL_PIXEL_FORMAT_BGR_565;
+      *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+      break;
+    case kFormatRGBA1010102Ubwc:
+      *target = HAL_PIXEL_FORMAT_RGBA_1010102;
+      *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+      break;
+    case kFormatRGBX1010102Ubwc:
+      *target = HAL_PIXEL_FORMAT_RGBX_1010102;
+      *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+      break;
+    default:
+      DLOGE("Unsupported format = 0x%x", format);
+      return -EINVAL;
+  }
+  return 0;
+}
+
+DisplayError HWCBufferAllocator::GetAllocatedBufferInfo(
+    const BufferConfig &buffer_config, AllocatedBufferInfo *allocated_buffer_info) {
+  // TODO(user): This API should pass the buffer_info of the already allocated buffer
+  // The private_data can then be typecast to the private_handle and used directly.
+  uint64_t alloc_flags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
+
+  int width = INT(buffer_config.width);
+  int height = INT(buffer_config.height);
+  int format;
+
+  if (buffer_config.secure) {
+    alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
+  }
+
+  if (!buffer_config.cache) {
+    // Allocate uncached buffers
+    alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+  }
+
+  if (SetBufferInfo(buffer_config.format, &format, &alloc_flags) < 0) {
+    return kErrorParameters;
+  }
+
+  uint32_t aligned_width = 0, aligned_height = 0, buffer_size = 0;
+  gralloc1_producer_usage_t producer_usage = GRALLOC1_PRODUCER_USAGE_NONE;
+  gralloc1_consumer_usage_t consumer_usage = GRALLOC1_CONSUMER_USAGE_NONE;
+  // TODO(user): Currently both flags are treated similarly in gralloc
+  producer_usage = gralloc1_producer_usage_t(alloc_flags);
+  consumer_usage = gralloc1_consumer_usage_t(alloc_flags);
+  gralloc1::BufferInfo info(width, height, format, producer_usage, consumer_usage);
+  GetBufferSizeAndDimensions(info, &buffer_size, &aligned_width, &aligned_height);
+  allocated_buffer_info->stride = UINT32(aligned_width);
+  allocated_buffer_info->aligned_width = UINT32(aligned_width);
+  allocated_buffer_info->aligned_height = UINT32(aligned_height);
+  allocated_buffer_info->size = UINT32(buffer_size);
+
+  return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::GetBufferLayout(const AllocatedBufferInfo &buf_info,
+                                                 uint32_t stride[4], uint32_t offset[4],
+                                                 uint32_t *num_planes) {
+  // TODO(user): Transition APIs to not need a private handle
+  private_handle_t hnd(-1, 0, 0, 0, 0, 0, 0);
+  int format = HAL_PIXEL_FORMAT_RGBA_8888;
+  uint64_t flags = 0;
+
+  SetBufferInfo(buf_info.format, &format, &flags);
+  // Setup only the required stuff, skip rest
+  hnd.format = format;
+  hnd.width = INT32(buf_info.aligned_width);
+  hnd.height = INT32(buf_info.aligned_height);
+  if (flags & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) {
+    hnd.flags = private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+  }
+
+  int ret = gralloc1::GetBufferLayout(&hnd, stride, offset, num_planes);
+  if (ret < 0) {
+    DLOGE("GetBufferLayout failed");
+    return kErrorParameters;
+  }
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc2/hwc_buffer_allocator.h b/sdm845/sdm/libs/hwc2/hwc_buffer_allocator.h
new file mode 100644
index 0000000..d574401
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_buffer_allocator.h
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2015-2017, 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.
+*/
+#ifdef USE_GRALLOC1
+#ifndef __HWC_BUFFER_ALLOCATOR_H__
+#define __HWC_BUFFER_ALLOCATOR_H__
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include <hardware/gralloc1.h>
+#include "gralloc_priv.h"
+
+namespace sdm {
+
+template <class Type>
+inline Type ALIGN(Type x, Type align) {
+  return (x + align - 1) & ~(align - 1);
+}
+
+class HWCBufferAllocator : public BufferAllocator {
+ public:
+  HWCBufferAllocator();
+  ~HWCBufferAllocator();
+
+  DisplayError AllocateBuffer(BufferInfo *buffer_info);
+  DisplayError FreeBuffer(BufferInfo *buffer_info);
+  uint32_t GetBufferSize(BufferInfo *buffer_info);
+
+  void GetCustomWidthAndHeight(const private_handle_t *handle, int *width, int *height);
+  void GetAlignedWidthAndHeight(int width, int height, int format, uint32_t alloc_type,
+                                int *aligned_width, int *aligned_height);
+  DisplayError GetAllocatedBufferInfo(const BufferConfig &buffer_config,
+                                      AllocatedBufferInfo *allocated_buffer_info);
+  DisplayError GetBufferLayout(const AllocatedBufferInfo &buf_info,
+                               uint32_t stride[4], uint32_t offset[4],
+                               uint32_t *num_planes);
+  int SetBufferInfo(LayerBufferFormat format, int *target, uint64_t *flags);
+
+ private:
+  gralloc1_device_t *gralloc_device_ = nullptr;
+  const hw_module_t *module_;
+  GRALLOC1_PFN_RELEASE ReleaseBuffer_ = nullptr;
+  GRALLOC1_PFN_PERFORM Perform_ = nullptr;
+};
+
+}  // namespace sdm
+#endif  // __HWC_BUFFER_ALLOCATOR_H__
+#else
+#include "../hwc/hwc_buffer_allocator.h"
+#endif  // __HWC_BUFFER_ALLOCATOR_H__
+
diff --git a/sdm845/sdm/libs/hwc2/hwc_callbacks.cpp b/sdm845/sdm/libs/hwc2/hwc_callbacks.cpp
new file mode 100644
index 0000000..48ae398
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_callbacks.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation. nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include "hwc_callbacks.h"
+
+#define __CLASS__ "HWCCallbacks"
+
+namespace sdm {
+
+void HWCCallbacks::Hotplug(hwc2_display_t display, HWC2::Connection state) {
+  if (hotplug_) {
+    hotplug_(hotplug_data_, display, INT32(state));
+  }
+}
+
+void HWCCallbacks::Refresh(hwc2_display_t display) {
+  if (refresh_) {
+    refresh_(refresh_data_, display);
+  }
+}
+
+void HWCCallbacks::Vsync(hwc2_display_t display, int64_t timestamp) {
+  if (vsync_) {
+    vsync_(vsync_data_, display, timestamp);
+  }
+}
+
+HWC2::Error HWCCallbacks::Register(HWC2::Callback descriptor, hwc2_callback_data_t callback_data,
+                                   hwc2_function_pointer_t pointer) {
+  switch (descriptor) {
+    case HWC2::Callback::Hotplug:
+      hotplug_data_ = callback_data;
+      hotplug_ = reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer);
+      break;
+    case HWC2::Callback::Refresh:
+      refresh_data_ = callback_data;
+      refresh_ = reinterpret_cast<HWC2_PFN_REFRESH>(pointer);
+      break;
+    case HWC2::Callback::Vsync:
+      vsync_data_ = callback_data;
+      vsync_ = reinterpret_cast<HWC2_PFN_VSYNC>(pointer);
+      break;
+    default:
+      return HWC2::Error::BadParameter;
+  }
+  return HWC2::Error::None;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc2/hwc_callbacks.h b/sdm845/sdm/libs/hwc2/hwc_callbacks.h
new file mode 100644
index 0000000..015bf5d
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_callbacks.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016-2017, 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_CALLBACKS_H__
+#define __HWC_CALLBACKS_H__
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+namespace sdm {
+
+class HWCCallbacks {
+ public:
+  void Hotplug(hwc2_display_t display, HWC2::Connection state);
+  void Refresh(hwc2_display_t display);
+  void Vsync(hwc2_display_t display, int64_t timestamp);
+  HWC2::Error Register(HWC2::Callback, hwc2_callback_data_t callback_data,
+                       hwc2_function_pointer_t pointer);
+
+  bool VsyncCallbackRegistered() { return (vsync_ != nullptr && vsync_data_ != nullptr); }
+
+ private:
+  hwc2_callback_data_t hotplug_data_ = nullptr;
+  hwc2_callback_data_t refresh_data_ = nullptr;
+  hwc2_callback_data_t vsync_data_ = nullptr;
+
+  HWC2_PFN_HOTPLUG hotplug_ = nullptr;
+  HWC2_PFN_REFRESH refresh_ = nullptr;
+  HWC2_PFN_VSYNC vsync_ = nullptr;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_CALLBACKS_H__
diff --git a/sdm845/sdm/libs/hwc2/hwc_color_manager.cpp b/sdm845/sdm/libs/hwc2/hwc_color_manager.cpp
new file mode 100644
index 0000000..9f336a0
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_color_manager.cpp
@@ -0,0 +1,500 @@
+/*
+* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <dlfcn.h>
+#include <powermanager/IPowerManager.h>
+#include <cutils/sockets.h>
+#include <cutils/native_handle.h>
+#include <utils/String16.h>
+#include <binder/Parcel.h>
+#include <gralloc_priv.h>
+#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer_defs.h>
+#include <QService.h>
+
+#include <core/dump_interface.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <core/buffer_allocator.h>
+#include <private/color_params.h>
+#include "hwc_buffer_allocator.h"
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_session.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCColorManager"
+
+namespace sdm {
+
+uint32_t HWCColorManager::Get8BitsARGBColorValue(const PPColorFillParams &params) {
+  uint32_t argb_color = ((params.color.r << 16) & 0xff0000) | ((params.color.g << 8) & 0xff00) |
+                        ((params.color.b) & 0xff);
+  return argb_color;
+}
+
+int HWCColorManager::CreatePayloadFromParcel(const android::Parcel &in, uint32_t *disp_id,
+                                             PPDisplayAPIPayload *sink) {
+  int ret = 0;
+  uint32_t id(0);
+  uint32_t size(0);
+
+  id = UINT32(in.readInt32());
+  size = UINT32(in.readInt32());
+  if (size > 0 && size == in.dataAvail()) {
+    const void *data = in.readInplace(size);
+    const uint8_t *temp = reinterpret_cast<const uint8_t *>(data);
+
+    sink->size = size;
+    sink->payload = const_cast<uint8_t *>(temp);
+    *disp_id = id;
+  } else {
+    DLOGW("Failing size checking, size = %d", size);
+    ret = -EINVAL;
+  }
+
+  return ret;
+}
+
+void HWCColorManager::MarshallStructIntoParcel(const PPDisplayAPIPayload &data,
+                                               android::Parcel *out_parcel) {
+  out_parcel->writeInt32(INT32(data.size));
+  if (data.payload)
+    out_parcel->write(data.payload, data.size);
+}
+
+HWCColorManager *HWCColorManager::CreateColorManager(HWCBufferAllocator * buffer_allocator) {
+  HWCColorManager *color_mgr = new HWCColorManager(buffer_allocator);
+
+  if (color_mgr) {
+    // Load display API interface library. And retrieve color API function tables.
+    DynLib &color_apis_lib = color_mgr->color_apis_lib_;
+    if (color_apis_lib.Open(DISPLAY_API_INTERFACE_LIBRARY_NAME)) {
+      if (!color_apis_lib.Sym(DISPLAY_API_FUNC_TABLES, &color_mgr->color_apis_)) {
+        DLOGE("Fail to retrieve = %s from %s", DISPLAY_API_FUNC_TABLES,
+              DISPLAY_API_INTERFACE_LIBRARY_NAME);
+        delete color_mgr;
+        return NULL;
+      }
+    } else {
+      DLOGW("Unable to load = %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
+      delete color_mgr;
+      return NULL;
+    }
+    DLOGI("Successfully loaded %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
+
+    // Load diagclient library and invokes its entry point to pass in display APIs.
+    DynLib &diag_client_lib = color_mgr->diag_client_lib_;
+    if (diag_client_lib.Open(QDCM_DIAG_CLIENT_LIBRARY_NAME)) {
+      if (!diag_client_lib.Sym(INIT_QDCM_DIAG_CLIENT_NAME,
+                               reinterpret_cast<void **>(&color_mgr->qdcm_diag_init_)) ||
+        !diag_client_lib.Sym(DEINIT_QDCM_DIAG_CLIENT_NAME,
+                               reinterpret_cast<void **>(&color_mgr->qdcm_diag_deinit_))) {
+        DLOGE("Fail to retrieve = %s from %s", INIT_QDCM_DIAG_CLIENT_NAME,
+              QDCM_DIAG_CLIENT_LIBRARY_NAME);
+      } else {
+        // invoke Diag Client entry point to initialize.
+        color_mgr->qdcm_diag_init_(color_mgr->color_apis_);
+        DLOGI("Successfully loaded %s and %s and diag_init'ed", DISPLAY_API_INTERFACE_LIBRARY_NAME,
+              QDCM_DIAG_CLIENT_LIBRARY_NAME);
+      }
+    } else {
+      DLOGW("Unable to load = %s", QDCM_DIAG_CLIENT_LIBRARY_NAME);
+      // only QDCM Diag client failed to be loaded and system still should function.
+    }
+  } else {
+    DLOGE("Unable to create HWCColorManager");
+    return NULL;
+  }
+
+  return color_mgr;
+}
+
+HWCColorManager::HWCColorManager(HWCBufferAllocator *buffer_allocator) :
+    buffer_allocator_(buffer_allocator) {
+}
+
+HWCColorManager::~HWCColorManager() {
+}
+
+void HWCColorManager::DestroyColorManager() {
+  if (qdcm_mode_mgr_) {
+    delete qdcm_mode_mgr_;
+  }
+  if (qdcm_diag_deinit_) {
+    qdcm_diag_deinit_();
+  }
+  delete this;
+}
+
+int HWCColorManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
+  int ret = 0;
+
+  if (!qdcm_mode_mgr_) {
+    qdcm_mode_mgr_ = HWCQDCMModeManager::CreateQDCMModeMgr();
+    if (!qdcm_mode_mgr_) {
+      DLOGE("Unable to create QDCM operating mode manager.");
+      ret = -EFAULT;
+    }
+  }
+
+  if (qdcm_mode_mgr_) {
+    ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display);
+  }
+
+  return ret;
+}
+
+int HWCColorManager::SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display) {
+  SCOPE_LOCK(locker_);
+
+  if (params) {
+    solid_fill_params_ = *reinterpret_cast<const PPColorFillParams *>(params);
+  } else {
+    solid_fill_params_ = PPColorFillParams();
+  }
+
+  uint32_t solid_fill_color = Get8BitsARGBColorValue(solid_fill_params_);
+  if (enable) {
+    LayerRect solid_fill_rect = {
+      FLOAT(solid_fill_params_.rect.x), FLOAT(solid_fill_params_.rect.y),
+      FLOAT(solid_fill_params_.rect.x) + FLOAT(solid_fill_params_.rect.width),
+      FLOAT(solid_fill_params_.rect.y) + FLOAT(solid_fill_params_.rect.height),
+    };
+
+    hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_INFO, solid_fill_color);
+    hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_RECT, &solid_fill_rect);
+  } else {
+    hwc_display->Perform(HWCDisplayPrimary::UNSET_QDCM_SOLID_FILL_INFO, 0);
+  }
+
+  return 0;
+}
+
+int HWCColorManager::SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display) {
+  SCOPE_LOCK(locker_);
+  int ret = 0;
+
+  PPFrameCaptureData *frame_capture_data = reinterpret_cast<PPFrameCaptureData *>(params);
+
+  if (enable) {
+    std::memset(&buffer_info, 0x00, sizeof(buffer_info));
+    hwc_display->GetPanelResolution(&buffer_info.buffer_config.width,
+                                    &buffer_info.buffer_config.height);
+    if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_888) {
+      buffer_info.buffer_config.format = kFormatRGB888;
+    } else if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_2101010) {
+      buffer_info.buffer_config.format = kFormatRGBA1010102;
+    } else {
+      DLOGE("Pixel-format: %d NOT support.", frame_capture_data->input_params.out_pix_format);
+      return -EFAULT;
+    }
+
+    buffer_info.buffer_config.buffer_count = 1;
+    buffer_info.alloc_buffer_info.fd = -1;
+    buffer_info.alloc_buffer_info.stride = 0;
+    buffer_info.alloc_buffer_info.size = 0;
+
+    ret = buffer_allocator_->AllocateBuffer(&buffer_info);
+    if (ret != 0) {
+      DLOGE("Buffer allocation failed. ret: %d", ret);
+      return -ENOMEM;
+    } else {
+      void *buffer = mmap(NULL, buffer_info.alloc_buffer_info.size, PROT_READ | PROT_WRITE,
+                          MAP_SHARED, buffer_info.alloc_buffer_info.fd, 0);
+
+      if (buffer == MAP_FAILED) {
+        DLOGE("mmap failed. err = %d", errno);
+        frame_capture_data->buffer = NULL;
+        ret = buffer_allocator_->FreeBuffer(&buffer_info);
+        return -EFAULT;
+      } else {
+        frame_capture_data->buffer = reinterpret_cast<uint8_t *>(buffer);
+        frame_capture_data->buffer_stride = buffer_info.buffer_config.width;
+        frame_capture_data->buffer_size = buffer_info.alloc_buffer_info.size;
+      }
+      ret = hwc_display->FrameCaptureAsync(buffer_info, 1);
+      if (ret < 0) {
+        DLOGE("FrameCaptureAsync failed. ret = %d", ret);
+      }
+    }
+  } else {
+    ret = hwc_display->GetFrameCaptureStatus();
+    if (!ret) {
+      if (frame_capture_data->buffer != NULL) {
+        if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) {
+          DLOGE("munmap failed. err = %d", errno);
+        }
+      }
+      if (buffer_allocator_ != NULL) {
+        std::memset(frame_capture_data, 0x00, sizeof(PPFrameCaptureData));
+        ret = buffer_allocator_->FreeBuffer(&buffer_info);
+        if (ret != 0) {
+          DLOGE("FreeBuffer failed. ret = %d", ret);
+        }
+      }
+    } else {
+      DLOGE("GetFrameCaptureStatus failed. ret = %d", ret);
+    }
+  }
+  return ret;
+}
+
+int HWCColorManager::SetHWDetailedEnhancerConfig(void *params, HWCDisplay *hwc_display) {
+  int err = -1;
+  DisplayDetailEnhancerData de_data;
+
+  PPDETuningCfgData *de_tuning_cfg_data = reinterpret_cast<PPDETuningCfgData*>(params);
+  if (de_tuning_cfg_data->cfg_pending == true) {
+    if (!de_tuning_cfg_data->cfg_en) {
+      de_data.override_flags = kOverrideDEEnable;
+      de_data.enable = 0;
+    } else {
+      de_data.override_flags = kOverrideDEEnable;
+      de_data.enable = 1;
+
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagSharpFactor) {
+        de_data.override_flags |= kOverrideDESharpen1;
+        de_data.sharp_factor = de_tuning_cfg_data->params.sharp_factor;
+      }
+
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagClip) {
+        de_data.override_flags |= kOverrideDEClip;
+        de_data.clip = de_tuning_cfg_data->params.clip;
+      }
+
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrQuiet) {
+        de_data.override_flags |= kOverrideDEThrQuiet;
+        de_data.thr_quiet = de_tuning_cfg_data->params.thr_quiet;
+      }
+
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrDieout) {
+        de_data.override_flags |= kOverrideDEThrDieout;
+        de_data.thr_dieout = de_tuning_cfg_data->params.thr_dieout;
+      }
+
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrLow) {
+        de_data.override_flags |= kOverrideDEThrLow;
+        de_data.thr_low = de_tuning_cfg_data->params.thr_low;
+      }
+
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrHigh) {
+        de_data.override_flags |= kOverrideDEThrHigh;
+        de_data.thr_high = de_tuning_cfg_data->params.thr_high;
+      }
+
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagContentQualLevel) {
+        switch (de_tuning_cfg_data->params.quality) {
+          case kDeContentQualLow:
+            de_data.quality_level = kContentQualityLow;
+            break;
+          case kDeContentQualMedium:
+            de_data.quality_level = kContentQualityMedium;
+            break;
+          case kDeContentQualHigh:
+            de_data.quality_level = kContentQualityHigh;
+            break;
+          case kDeContentQualUnknown:
+          default:
+            de_data.quality_level = kContentQualityUnknown;
+            break;
+        }
+      }
+    }
+    err = hwc_display->SetDetailEnhancerConfig(de_data);
+    if (err) {
+      DLOGW("SetDetailEnhancerConfig failed. err = %d", err);
+    }
+    de_tuning_cfg_data->cfg_pending = false;
+  }
+  return err;
+}
+
+void HWCColorManager::SetColorModeDetailEnhancer(HWCDisplay *hwc_display) {
+  SCOPE_LOCK(locker_);
+  int err = -1;
+  PPPendingParams pending_action;
+  PPDisplayAPIPayload req_payload;
+
+  pending_action.action = kGetDetailedEnhancerData;
+  pending_action.params = NULL;
+
+  if (hwc_display) {
+    err = hwc_display->ColorSVCRequestRoute(req_payload, NULL, &pending_action);
+    if (!err && pending_action.action == kConfigureDetailedEnhancer) {
+      err = SetHWDetailedEnhancerConfig(pending_action.params, hwc_display);
+    }
+  }
+  return;
+}
+
+int HWCColorManager::SetDetailedEnhancer(void *params, HWCDisplay *hwc_display) {
+  SCOPE_LOCK(locker_);
+  int err = -1;
+  err = SetHWDetailedEnhancerConfig(params, hwc_display);
+  return err;
+}
+
+const HWCQDCMModeManager::ActiveFeatureCMD HWCQDCMModeManager::kActiveFeatureCMD[] = {
+    HWCQDCMModeManager::ActiveFeatureCMD("cabl:on", "cabl:off", "cabl:status", "running"),
+    HWCQDCMModeManager::ActiveFeatureCMD("ad:on", "ad:off", "ad:query:status", "running"),
+    HWCQDCMModeManager::ActiveFeatureCMD("svi:on", "svi:off", "svi:status", "running"),
+};
+
+const char *const HWCQDCMModeManager::kSocketName = "pps";
+const char *const HWCQDCMModeManager::kTagName = "surfaceflinger";
+const char *const HWCQDCMModeManager::kPackageName = "colormanager";
+
+HWCQDCMModeManager *HWCQDCMModeManager::CreateQDCMModeMgr() {
+  HWCQDCMModeManager *mode_mgr = new HWCQDCMModeManager();
+
+  if (!mode_mgr) {
+    DLOGW("No memory to create HWCQDCMModeManager.");
+    return NULL;
+  } else {
+    mode_mgr->socket_fd_ =
+        ::socket_local_client(kSocketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+    if (mode_mgr->socket_fd_ < 0) {
+      // it should not be disastrous and we still can grab wakelock in QDCM mode.
+      DLOGW("Unable to connect to dpps socket!");
+    }
+
+    // retrieve system GPU idle timeout value for later to recover.
+    mode_mgr->entry_timeout_ = UINT32(HWCDebugHandler::GetIdleTimeoutMs());
+
+    // acquire the binder handle to Android system PowerManager for later use.
+    android::sp<android::IBinder> binder =
+        android::defaultServiceManager()->checkService(android::String16("power"));
+    if (binder == NULL) {
+      DLOGW("Application can't connect to  power manager service");
+      delete mode_mgr;
+      mode_mgr = NULL;
+    } else {
+      mode_mgr->power_mgr_ = android::interface_cast<android::IPowerManager>(binder);
+    }
+  }
+
+  return mode_mgr;
+}
+
+HWCQDCMModeManager::~HWCQDCMModeManager() {
+  if (socket_fd_ >= 0)
+    ::close(socket_fd_);
+}
+
+int HWCQDCMModeManager::AcquireAndroidWakeLock(bool enable) {
+  int ret = 0;
+
+  if (enable) {
+    if (wakelock_token_ == NULL) {
+      android::sp<android::IBinder> binder = new android::BBinder();
+      android::status_t status = power_mgr_->acquireWakeLock(
+          (kFullWakeLock | kAcquireCauseWakeup | kONAfterRelease), binder,
+          android::String16(kTagName), android::String16(kPackageName));
+      if (status == android::NO_ERROR) {
+        wakelock_token_ = binder;
+      }
+    }
+  } else {
+    if (wakelock_token_ != NULL && power_mgr_ != NULL) {
+      power_mgr_->releaseWakeLock(wakelock_token_, 0);
+      wakelock_token_.clear();
+      wakelock_token_ = NULL;
+    }
+  }
+
+  return ret;
+}
+
+int HWCQDCMModeManager::EnableActiveFeatures(bool enable,
+                                             const HWCQDCMModeManager::ActiveFeatureCMD &cmds,
+                                             bool *was_running) {
+  int ret = 0;
+  ssize_t size = 0;
+  char response[kSocketCMDMaxLength] = {
+      0,
+  };
+
+  if (socket_fd_ < 0) {
+    DLOGW("No socket connection available!");
+    return -EFAULT;
+  }
+
+  if (!enable) {  // if client requesting to disable it.
+    // query CABL status, if off, no action. keep the status.
+    size = ::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status));
+    if (size < 0) {
+      DLOGW("Unable to send data over socket %s", ::strerror(errno));
+      ret = -EFAULT;
+    } else {
+      size = ::read(socket_fd_, response, kSocketCMDMaxLength);
+      if (size < 0) {
+        DLOGW("Unable to read data over socket %s", ::strerror(errno));
+        ret = -EFAULT;
+      } else if (!strncmp(response, cmds.running, strlen(cmds.running))) {
+        *was_running = true;
+      }
+    }
+
+    if (*was_running) {  // if was running, it's requested to disable it.
+      size = ::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off));
+      if (size < 0) {
+        DLOGW("Unable to send data over socket %s", ::strerror(errno));
+        ret = -EFAULT;
+      }
+    }
+  } else {  // if was running, need enable it back.
+    if (*was_running) {
+      size = ::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on));
+      if (size < 0) {
+        DLOGW("Unable to send data over socket %s", ::strerror(errno));
+        ret = -EFAULT;
+      }
+    }
+  }
+
+  return ret;
+}
+
+int HWCQDCMModeManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
+  int ret = 0;
+
+  ret = EnableActiveFeatures((enable ? false : true), kActiveFeatureCMD[kCABLFeature],
+                             &cabl_was_running_);
+  ret = AcquireAndroidWakeLock(enable);
+
+  // if enter QDCM mode, disable GPU fallback idle timeout.
+  if (hwc_display) {
+    uint32_t timeout = enable ? 0 : entry_timeout_;
+    hwc_display->SetIdleTimeoutMs(timeout);
+  }
+
+  return ret;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc2/hwc_color_manager.h b/sdm845/sdm/libs/hwc2/hwc_color_manager.h
new file mode 100644
index 0000000..62d5535
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_color_manager.h
@@ -0,0 +1,145 @@
+/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* 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_COLOR_MANAGER_H__
+#define __HWC_COLOR_MANAGER_H__
+
+#include <stdlib.h>
+#include <binder/Parcel.h>
+#include <powermanager/IPowerManager.h>
+#include <binder/BinderService.h>
+#include <core/sdm_types.h>
+#include <utils/locker.h>
+
+namespace sdm {
+
+// This macro defines name for display APIs interface wrapper library.
+// This macro shall be used to load library using dlopen().
+#define DISPLAY_API_INTERFACE_LIBRARY_NAME "libsdm-disp-vndapis.so"
+
+// This macro defines variable name of display color APIs function tables
+// This macro shall be used to specify name of the variable in dlsym().
+#define DISPLAY_API_FUNC_TABLES "display_color_apis_ftables"
+#define QDCM_DIAG_CLIENT_LIBRARY_NAME "libsdm-diag.so"
+#define INIT_QDCM_DIAG_CLIENT_NAME "QDCMDiagInit"
+#define DEINIT_QDCM_DIAG_CLIENT_NAME "QDCMDiagDeInit"
+
+typedef int (*QDCMDiagInit)(void *ftables);
+
+typedef int (*QDCMDiagDeInit)(void);
+
+// Class to encapsulte all details of managing QDCM operating mode.
+class HWCQDCMModeManager {
+ public:
+  static const uint32_t kSocketCMDMaxLength = 4096;
+  static const uint32_t kFullWakeLock = 0x0000001a;
+  static const uint32_t kAcquireCauseWakeup = 0x10000000;
+  static const uint32_t kONAfterRelease = 0x20000000;
+  enum ActiveFeatureID {
+    kCABLFeature,
+    kADFeature,
+    kSVIFeature,
+    kMaxNumActiveFeature,
+  };
+
+  struct ActiveFeatureCMD {
+    const char *cmd_on = NULL;
+    const char *cmd_off = NULL;
+    const char *cmd_query_status = NULL;
+    const char *running = NULL;
+    ActiveFeatureCMD(const char *arg1, const char *arg2, const char *arg3, const char *arg4)
+        : cmd_on(arg1), cmd_off(arg2), cmd_query_status(arg3), running(arg4) {}
+  };
+
+  static const ActiveFeatureCMD kActiveFeatureCMD[kMaxNumActiveFeature];
+
+ public:
+  static HWCQDCMModeManager *CreateQDCMModeMgr();
+  ~HWCQDCMModeManager();
+  int EnableQDCMMode(bool enable, HWCDisplay *hwc_display);
+
+ protected:
+  bool SendSocketCmd();
+  int AcquireAndroidWakeLock(bool enable);
+  int EnableActiveFeatures(bool enable);
+  int EnableActiveFeatures(bool enable, const ActiveFeatureCMD &cmds, bool *was_running);
+
+ private:
+  bool cabl_was_running_ = false;
+  int socket_fd_ = -1;
+  android::sp<android::IBinder> wakelock_token_ = NULL;
+  android::sp<android::IPowerManager> power_mgr_ = NULL;
+  uint32_t entry_timeout_ = 0;
+  static const char *const kSocketName;
+  static const char *const kTagName;
+  static const char *const kPackageName;
+};
+
+// Class to encapsulte all HWC/OS specific behaviours for ColorManager.
+class HWCColorManager {
+ public:
+  static const int kNumSolidFillLayers = 2;
+  static HWCColorManager *CreateColorManager(HWCBufferAllocator *buffer_allocator);
+  static int CreatePayloadFromParcel(const android::Parcel &in, uint32_t *disp_id,
+                                     PPDisplayAPIPayload *sink);
+  static void MarshallStructIntoParcel(const PPDisplayAPIPayload &data,
+                                       android::Parcel *out_parcel);
+
+  explicit HWCColorManager(HWCBufferAllocator *buffer_allocator);
+  ~HWCColorManager();
+  void DestroyColorManager();
+  int EnableQDCMMode(bool enable, HWCDisplay *hwc_display);
+  int SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display);
+  int SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display);
+  int SetDetailedEnhancer(void *params, HWCDisplay *hwc_display);
+  void SetColorModeDetailEnhancer(HWCDisplay *hwc_display);
+  int SetHWDetailedEnhancerConfig(void *params, HWCDisplay *hwc_display);
+
+ protected:
+  int CreateSolidFillLayers(HWCDisplay *hwc_display);
+  void DestroySolidFillLayers();
+  static uint32_t Get8BitsARGBColorValue(const PPColorFillParams &params);
+
+ private:
+  DynLib color_apis_lib_;
+  DynLib diag_client_lib_;
+  void *color_apis_ = NULL;
+  QDCMDiagInit qdcm_diag_init_ = NULL;
+  QDCMDiagDeInit qdcm_diag_deinit_ = NULL;
+  HWCQDCMModeManager *qdcm_mode_mgr_ = NULL;
+
+  PPColorFillParams solid_fill_params_;
+  HWCBufferAllocator *buffer_allocator_ = NULL;
+  BufferInfo buffer_info;
+  Locker locker_;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_COLOR_MANAGER_H__
diff --git a/sdm845/sdm/libs/hwc2/hwc_display.cpp b/sdm845/sdm/libs/hwc2/hwc_display.cpp
new file mode 100644
index 0000000..4f623ce
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_display.cpp
@@ -0,0 +1,1848 @@
+/*
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cutils/properties.h>
+#include <errno.h>
+#include <math.h>
+#include <sync/sync.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/formats.h>
+#include <utils/rect.h>
+#include <qd_utils.h>
+
+#include <algorithm>
+#include <iomanip>
+#include <map>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "hwc_display.h"
+#include "hwc_debugger.h"
+#include "blit_engine_c2d.h"
+#include "hwc_tonemapper.h"
+
+#ifndef USE_GRALLOC1
+#include <gr.h>
+#endif
+
+#ifdef QTI_BSP
+#include <hardware/display_defs.h>
+#endif
+
+#define __CLASS__ "HWCDisplay"
+
+namespace sdm {
+
+// This weight function is needed because the color primaries are not sorted by gamut size
+static ColorPrimaries WidestPrimaries(ColorPrimaries p1, ColorPrimaries p2) {
+  int weight = 10;
+  int lp1 = p1, lp2 = p2;
+  // TODO(user) add weight to other wide gamut primaries
+  if (lp1 == ColorPrimaries_BT2020) {
+    lp1 *= weight;
+  }
+  if (lp1 == ColorPrimaries_BT2020) {
+    lp2 *= weight;
+  }
+  if (lp1 >= lp2) {
+    return p1;
+  } else {
+    return p2;
+  }
+}
+
+HWCColorMode::HWCColorMode(DisplayInterface *display_intf) : display_intf_(display_intf) {}
+
+HWC2::Error HWCColorMode::Init() {
+  PopulateColorModes();
+  return ApplyDefaultColorMode();
+}
+
+HWC2::Error HWCColorMode::DeInit() {
+  color_mode_transform_map_.clear();
+  return HWC2::Error::None;
+}
+
+uint32_t HWCColorMode::GetColorModeCount() {
+  uint32_t count = UINT32(color_mode_transform_map_.size());
+  DLOGI("Supported color mode count = %d", count);
+
+  return std::max(1U, count);
+}
+
+HWC2::Error HWCColorMode::GetColorModes(uint32_t *out_num_modes,
+                                        android_color_mode_t *out_modes) {
+  auto it = color_mode_transform_map_.begin();
+  for (auto i = 0; it != color_mode_transform_map_.end(); it++, i++) {
+    out_modes[i] = it->first;
+    DLOGI("Supports color mode[%d] = %d", i, it->first);
+  }
+  *out_num_modes = UINT32(color_mode_transform_map_.size());
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCColorMode::SetColorMode(android_color_mode_t mode) {
+  // first mode in 2D matrix is the mode (identity)
+  if (color_mode_transform_map_.find(mode) == color_mode_transform_map_.end()) {
+    DLOGE("Could not find mode: %d", mode);
+    return HWC2::Error::BadParameter;
+  }
+  auto status = HandleColorModeTransform(mode, current_color_transform_, color_matrix_);
+  if (status != HWC2::Error::None) {
+    DLOGE("failed for mode = %d", mode);
+  }
+
+  return status;
+}
+
+HWC2::Error HWCColorMode::SetColorModeById(int32_t color_mode_id) {
+  DLOGI("Applying mode: %d", color_mode_id);
+  DisplayError error = display_intf_->SetColorModeById(color_mode_id);
+  if (error != kErrorNone) {
+    return HWC2::Error::BadParameter;
+  }
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCColorMode::SetColorTransform(const float *matrix, android_color_transform_t hint) {
+  if (!matrix) {
+    return HWC2::Error::BadParameter;
+  }
+
+  double color_matrix[kColorTransformMatrixCount] = {0};
+  CopyColorTransformMatrix(matrix, color_matrix);
+
+  auto status = HandleColorModeTransform(current_color_mode_, hint, color_matrix);
+  if (status != HWC2::Error::None) {
+    DLOGE("failed for hint = %d", hint);
+  }
+
+  return status;
+}
+
+HWC2::Error HWCColorMode::HandleColorModeTransform(android_color_mode_t mode,
+                                                   android_color_transform_t hint,
+                                                   const double *matrix) {
+  android_color_transform_t transform_hint = hint;
+  std::string color_mode_transform;
+  bool use_matrix = false;
+  if (hint != HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX) {
+    // if the mode + transfrom request from HWC matches one mode in SDM, set that
+    if (color_mode_transform.empty()) {
+      transform_hint = HAL_COLOR_TRANSFORM_IDENTITY;
+      use_matrix = true;
+    } else {
+      color_mode_transform = color_mode_transform_map_[mode][hint];
+    }
+  } else {
+    use_matrix = true;
+    transform_hint = HAL_COLOR_TRANSFORM_IDENTITY;
+  }
+
+  // if the mode count is 1, then only native mode is supported, so just apply matrix w/o
+  // setting mode
+  if (color_mode_transform_map_.size() > 1U) {
+    color_mode_transform = color_mode_transform_map_[mode][transform_hint];
+    DisplayError error = display_intf_->SetColorMode(color_mode_transform);
+    if (error != kErrorNone) {
+      DLOGE("Failed to set color_mode  = %d transform_hint = %d", mode, hint);
+      // failure to force client composition
+      return HWC2::Error::Unsupported;
+    }
+  }
+
+  if (use_matrix) {
+    DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, matrix);
+    if (error != kErrorNone) {
+      DLOGE("Failed to set Color Transform Matrix");
+      // failure to force client composition
+      return HWC2::Error::Unsupported;
+    }
+  }
+
+  current_color_mode_ = mode;
+  current_color_transform_ = hint;
+  CopyColorTransformMatrix(matrix, color_matrix_);
+  DLOGI("Setting Color Mode = %d Transform Hint = %d Success", mode, hint);
+
+  return HWC2::Error::None;
+}
+
+void HWCColorMode::PopulateColorModes() {
+  uint32_t color_mode_count = 0;
+  // SDM returns modes which is string combination of mode + transform.
+  DisplayError error = display_intf_->GetColorModeCount(&color_mode_count);
+  if (error != kErrorNone || (color_mode_count == 0)) {
+    DLOGW("GetColorModeCount failed, use native color mode");
+    PopulateTransform(HAL_COLOR_MODE_NATIVE, "native", "identity");
+    return;
+  }
+
+  DLOGV_IF(kTagQDCM, "Color Modes supported count = %d", color_mode_count);
+
+  const std::string color_transform = "identity";
+  std::vector<std::string> color_modes(color_mode_count);
+  error = display_intf_->GetColorModes(&color_mode_count, &color_modes);
+  for (uint32_t i = 0; i < color_mode_count; i++) {
+    std::string &mode_string = color_modes.at(i);
+    DLOGV_IF(kTagQDCM, "Color Mode[%d] = %s", i, mode_string.c_str());
+    AttrVal attr;
+    error = display_intf_->GetColorModeAttr(mode_string, &attr);
+    if (!attr.empty()) {
+      std::string color_gamut, dynamic_range, pic_quality;
+      for (auto &it : attr) {
+        if (it.first.find(kColorGamutAttribute) != std::string::npos) {
+          color_gamut = it.second;
+        } else if (it.first.find(kDynamicRangeAttribute) != std::string::npos) {
+          dynamic_range = it.second;
+        } else if (it.first.find(kPictureQualityAttribute) != std::string::npos) {
+          pic_quality = it.second;
+        }
+      }
+      if (dynamic_range == kHdr) {
+        continue;
+      }
+      if ((color_gamut == kNative) &&
+          (pic_quality.empty() || pic_quality == kStandard)) {
+        PopulateTransform(HAL_COLOR_MODE_NATIVE, mode_string, color_transform);
+      } else if ((color_gamut == kSrgb) &&
+                 (pic_quality.empty() || pic_quality == kStandard)) {
+        PopulateTransform(HAL_COLOR_MODE_SRGB, mode_string, color_transform);
+      } else if ((color_gamut == kDcip3) &&
+                 (pic_quality.empty() || pic_quality == kStandard)) {
+        PopulateTransform(HAL_COLOR_MODE_DCI_P3, mode_string, color_transform);
+      } else if ((color_gamut == kDisplayP3) &&
+                 (pic_quality.empty() || pic_quality == kStandard)) {
+        PopulateTransform(HAL_COLOR_MODE_DISPLAY_P3, mode_string, color_transform);
+      }
+    } else {
+      if (mode_string.find("hal_native") != std::string::npos) {
+        PopulateTransform(HAL_COLOR_MODE_NATIVE, mode_string, mode_string);
+      } else if (mode_string.find("hal_srgb") != std::string::npos) {
+        PopulateTransform(HAL_COLOR_MODE_SRGB, mode_string, mode_string);
+      } else if (mode_string.find("hal_adobe") != std::string::npos) {
+        PopulateTransform(HAL_COLOR_MODE_ADOBE_RGB, mode_string, mode_string);
+      } else if (mode_string.find("hal_dci_p3") != std::string::npos) {
+        PopulateTransform(HAL_COLOR_MODE_DCI_P3, mode_string, mode_string);
+      } else if (mode_string.find("hal_display_p3") != std::string::npos) {
+        PopulateTransform(HAL_COLOR_MODE_DISPLAY_P3, mode_string, mode_string);
+      }
+    }
+  }
+}
+
+void HWCColorMode::PopulateTransform(const android_color_mode_t &mode,
+                                     const std::string &color_mode,
+                                     const std::string &color_transform) {
+  // TODO(user): Check the substring from QDCM
+  if (color_transform.find("identity") != std::string::npos) {
+    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_IDENTITY] = color_mode;
+  } else if (color_transform.find("arbitrary") != std::string::npos) {
+    // no color mode for arbitrary
+  } else if (color_transform.find("inverse") != std::string::npos) {
+    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_VALUE_INVERSE] = color_mode;
+  } else if (color_transform.find("grayscale") != std::string::npos) {
+    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_GRAYSCALE] = color_mode;
+  } else if (color_transform.find("correct_protonopia") != std::string::npos) {
+    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_CORRECT_PROTANOPIA] = color_mode;
+  } else if (color_transform.find("correct_deuteranopia") != std::string::npos) {
+    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_CORRECT_DEUTERANOPIA] = color_mode;
+  } else if (color_transform.find("correct_tritanopia") != std::string::npos) {
+    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA] = color_mode;
+  } else {
+    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_IDENTITY] = color_mode;
+  }
+}
+
+HWC2::Error HWCColorMode::ApplyDefaultColorMode() {
+  android_color_mode_t color_mode = HAL_COLOR_MODE_NATIVE;
+  if (color_mode_transform_map_.size() == 1U) {
+    color_mode = color_mode_transform_map_.begin()->first;
+  } else if (color_mode_transform_map_.size() > 1U) {
+    std::string default_color_mode;
+    bool found = false;
+    DisplayError error = display_intf_->GetDefaultColorMode(&default_color_mode);
+    if (error == kErrorNone) {
+      // get the default mode corresponding android_color_mode_t
+      for (auto &it_mode : color_mode_transform_map_) {
+        for (auto &it : it_mode.second) {
+          if (it.second == default_color_mode) {
+            found = true;
+            break;
+          }
+        }
+        if (found) {
+          color_mode = it_mode.first;
+          break;
+        }
+      }
+    }
+
+    // return the first andrid_color_mode_t when we encouter if not found
+    if (!found) {
+      color_mode = color_mode_transform_map_.begin()->first;
+    }
+  }
+  return SetColorMode(color_mode);
+}
+
+void HWCColorMode::Dump(std::ostringstream* os) {
+  *os << "color modes supported: ";
+  for (auto it : color_mode_transform_map_) {
+    *os << it.first <<" ";
+  }
+  *os << "current mode: " << current_color_mode_ << std::endl;
+  *os << "current transform: ";
+  for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
+    if (i % 4 == 0) {
+     *os << std::endl;
+    }
+    *os << std::fixed << std::setprecision(2) << std::setw(6) << std::setfill(' ')
+        << color_matrix_[i] << " ";
+  }
+  *os << std::endl;
+}
+
+HWCDisplay::HWCDisplay(CoreInterface *core_intf, HWCCallbacks *callbacks, DisplayType type,
+                       hwc2_display_t id, bool needs_blit, qService::QService *qservice,
+                       DisplayClass display_class, BufferAllocator *buffer_allocator)
+    : core_intf_(core_intf),
+      callbacks_(callbacks),
+      type_(type),
+      id_(id),
+      needs_blit_(needs_blit),
+      qservice_(qservice),
+      display_class_(display_class) {
+  buffer_allocator_ = static_cast<HWCBufferAllocator *>(buffer_allocator);
+}
+
+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;
+  }
+
+  HWCDebugHandler::Get()->GetProperty("sys.hwc_disable_hdr", &disable_hdr_handling_);
+  if (disable_hdr_handling_) {
+    DLOGI("HDR Handling disabled");
+  }
+
+  int property_swap_interval = 1;
+  HWCDebugHandler::Get()->GetProperty("debug.egl.swapinterval", &property_swap_interval);
+  if (property_swap_interval == 0) {
+    swap_interval_zero_ = true;
+  }
+
+  client_target_ = new HWCLayer(id_, buffer_allocator_);
+
+  int blit_enabled = 0;
+  HWCDebugHandler::Get()->GetProperty("persist.hwc.blit.comp", &blit_enabled);
+  if (needs_blit_ && blit_enabled) {
+    // TODO(user): Add blit engine when needed
+  }
+
+  tone_mapper_ = new HWCToneMapper(buffer_allocator_);
+
+  display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
+  current_refresh_rate_ = max_refresh_rate_;
+  DLOGI("Display created with id: %d", id_);
+  return 0;
+}
+
+int HWCDisplay::Deinit() {
+  DisplayError error = core_intf_->DestroyDisplay(display_intf_);
+  if (error != kErrorNone) {
+    DLOGE("Display destroy failed. Error = %d", error);
+    return -EINVAL;
+  }
+
+  delete client_target_;
+
+  if (color_mode_) {
+    color_mode_->DeInit();
+    delete color_mode_;
+  }
+
+  delete tone_mapper_;
+  tone_mapper_ = nullptr;
+
+  return 0;
+}
+
+// LayerStack operations
+HWC2::Error HWCDisplay::CreateLayer(hwc2_layer_t *out_layer_id) {
+  HWCLayer *layer = *layer_set_.emplace(new HWCLayer(id_, buffer_allocator_));
+  layer_map_.emplace(std::make_pair(layer->GetId(), layer));
+  *out_layer_id = layer->GetId();
+  validated_ = false;
+  geometry_changes_ |= GeometryChanges::kAdded;
+  return HWC2::Error::None;
+}
+
+HWCLayer *HWCDisplay::GetHWCLayer(hwc2_layer_t layer_id) {
+  const auto map_layer = layer_map_.find(layer_id);
+  if (map_layer == layer_map_.end()) {
+    DLOGE("[%" PRIu64 "] GetLayer(%" PRIu64 ") failed: no such layer", id_, layer_id);
+    return nullptr;
+  } else {
+    return map_layer->second;
+  }
+}
+
+HWC2::Error HWCDisplay::DestroyLayer(hwc2_layer_t layer_id) {
+  const auto map_layer = layer_map_.find(layer_id);
+  if (map_layer == layer_map_.end()) {
+    DLOGE("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer", id_, layer_id);
+    return HWC2::Error::BadLayer;
+  }
+  const auto layer = map_layer->second;
+  layer_map_.erase(map_layer);
+  const auto z_range = layer_set_.equal_range(layer);
+  for (auto current = z_range.first; current != z_range.second; ++current) {
+    if (*current == layer) {
+      current = layer_set_.erase(current);
+      delete layer;
+      break;
+    }
+  }
+  validated_ = false;
+
+  geometry_changes_ |= GeometryChanges::kRemoved;
+  return HWC2::Error::None;
+}
+
+
+void HWCDisplay::BuildLayerStack() {
+  layer_stack_ = LayerStack();
+  display_rect_ = LayerRect();
+  metadata_refresh_rate_ = 0;
+  auto working_primaries = ColorPrimaries_BT709_5;
+
+  // Add one layer for fb target
+  // TODO(user): Add blit target layers
+  for (auto hwc_layer : layer_set_) {
+    // Reset layer data which SDM may change
+    hwc_layer->ResetPerFrameData();
+
+    Layer *layer = hwc_layer->GetSDMLayer();
+    layer->flags = {};   // Reset earlier flags
+    if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Client) {
+      layer->flags.skip = true;
+    } else if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::SolidColor) {
+      layer->flags.solid_fill = true;
+    }
+
+#ifdef FEATURE_WIDE_COLOR
+    if (!hwc_layer->SupportedDataspace()) {
+        layer->flags.skip = true;
+        DLOGW_IF(kTagStrategy, "Unsupported dataspace: 0x%x", hwc_layer->GetLayerDataspace());
+    }
+#endif
+
+    working_primaries = WidestPrimaries(working_primaries,
+                                        layer->input_buffer.color_metadata.colorPrimaries);
+
+    // set default composition as GPU for SDM
+    layer->composition = kCompositionGPU;
+
+    if (swap_interval_zero_) {
+      if (layer->input_buffer.acquire_fence_fd >= 0) {
+        close(layer->input_buffer.acquire_fence_fd);
+        layer->input_buffer.acquire_fence_fd = -1;
+      }
+    }
+
+    const private_handle_t *handle =
+        reinterpret_cast<const private_handle_t *>(layer->input_buffer.buffer_id);
+    if (handle) {
+#ifdef USE_GRALLOC1
+      if (handle->buffer_type == BUFFER_TYPE_VIDEO) {
+#else
+      if (handle->bufferType == BUFFER_TYPE_VIDEO) {
+#endif
+        layer_stack_.flags.video_present = true;
+      }
+      // TZ Protected Buffer - L1
+      if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+        layer_stack_.flags.secure_present = true;
+      }
+      // Gralloc Usage Protected Buffer - L3 - which needs to be treated as Secure & avoid fallback
+      if (handle->flags & private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER) {
+        layer_stack_.flags.secure_present = true;
+      }
+    }
+
+    if (layer->flags.skip) {
+      layer_stack_.flags.skip_present = true;
+    }
+
+    if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Cursor) {
+      // Currently we support only one HWCursor & only at top most z-order
+      if ((*layer_set_.rbegin())->GetId() == hwc_layer->GetId()) {
+        layer->flags.cursor = true;
+        layer_stack_.flags.cursor_present = true;
+      }
+    }
+
+    bool hdr_layer = layer->input_buffer.color_metadata.colorPrimaries == ColorPrimaries_BT2020 &&
+                     (layer->input_buffer.color_metadata.transfer == Transfer_SMPTE_ST2084 ||
+                     layer->input_buffer.color_metadata.transfer == Transfer_HLG);
+    if (hdr_layer && !disable_hdr_handling_) {
+      // dont honor HDR when its handling is disabled
+      layer->input_buffer.flags.hdr = true;
+      layer_stack_.flags.hdr_present = true;
+    }
+
+    // TODO(user): Move to a getter if this is needed at other places
+    hwc_rect_t scaled_display_frame = {INT(layer->dst_rect.left), INT(layer->dst_rect.top),
+                                       INT(layer->dst_rect.right), INT(layer->dst_rect.bottom)};
+    ApplyScanAdjustment(&scaled_display_frame);
+    hwc_layer->SetLayerDisplayFrame(scaled_display_frame);
+    // SDM requires these details even for solid fill
+    if (layer->flags.solid_fill) {
+      LayerBuffer *layer_buffer = &layer->input_buffer;
+      layer_buffer->width = UINT32(layer->dst_rect.right - layer->dst_rect.left);
+      layer_buffer->height = UINT32(layer->dst_rect.bottom - layer->dst_rect.top);
+      layer_buffer->unaligned_width = layer_buffer->width;
+      layer_buffer->unaligned_height = layer_buffer->height;
+      layer_buffer->acquire_fence_fd = -1;
+      layer_buffer->release_fence_fd = -1;
+      layer->src_rect.left = 0;
+      layer->src_rect.top = 0;
+      layer->src_rect.right = layer_buffer->width;
+      layer->src_rect.bottom = layer_buffer->height;
+    }
+
+    if (layer->frame_rate > metadata_refresh_rate_) {
+      metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
+    } else {
+      layer->frame_rate = current_refresh_rate_;
+    }
+    display_rect_ = Union(display_rect_, layer->dst_rect);
+    geometry_changes_ |= hwc_layer->GetGeometryChanges();
+
+    layer->flags.updating = true;
+    if (layer_set_.size() <= kMaxLayerCount) {
+      layer->flags.updating = IsLayerUpdating(layer);
+    }
+
+    layer_stack_.layers.push_back(layer);
+  }
+
+
+#ifdef FEATURE_WIDE_COLOR
+  for (auto hwc_layer : layer_set_) {
+    auto layer = hwc_layer->GetSDMLayer();
+    if (layer->input_buffer.color_metadata.colorPrimaries != working_primaries &&
+        !hwc_layer->SupportLocalConversion(working_primaries)) {
+      layer->flags.skip = true;
+    }
+    if (layer->flags.skip) {
+      layer_stack_.flags.skip_present = true;
+    }
+  }
+#endif
+
+  // TODO(user): Set correctly when SDM supports geometry_changes as bitmask
+  layer_stack_.flags.geometry_changed = UINT32(geometry_changes_ > 0);
+  // Append client target to the layer stack
+  layer_stack_.layers.push_back(client_target_->GetSDMLayer());
+}
+
+void HWCDisplay::BuildSolidFillStack() {
+  layer_stack_ = LayerStack();
+  display_rect_ = LayerRect();
+
+  layer_stack_.layers.push_back(solid_fill_layer_);
+  layer_stack_.flags.geometry_changed = 1U;
+  // Append client target to the layer stack
+  layer_stack_.layers.push_back(client_target_->GetSDMLayer());
+}
+
+HWC2::Error HWCDisplay::SetLayerZOrder(hwc2_layer_t layer_id, uint32_t z) {
+  const auto map_layer = layer_map_.find(layer_id);
+  if (map_layer == layer_map_.end()) {
+    DLOGE("[%" PRIu64 "] updateLayerZ failed to find layer", id_);
+    return HWC2::Error::BadLayer;
+  }
+  validated_ = false;
+
+  const auto layer = map_layer->second;
+  const auto z_range = layer_set_.equal_range(layer);
+  bool layer_on_display = false;
+  for (auto current = z_range.first; current != z_range.second; ++current) {
+    if (*current == layer) {
+      if ((*current)->GetZ() == z) {
+        // Don't change anything if the Z hasn't changed
+        return HWC2::Error::None;
+      }
+      current = layer_set_.erase(current);
+      layer_on_display = true;
+      break;
+    }
+  }
+
+  if (!layer_on_display) {
+    DLOGE("[%" PRIu64 "] updateLayerZ failed to find layer on display", id_);
+    return HWC2::Error::BadLayer;
+  }
+
+  layer->SetLayerZOrder(z);
+  layer_set_.emplace(layer);
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::SetVsyncEnabled(HWC2::Vsync enabled) {
+  DLOGV("Display ID: %d enabled: %s", id_, to_string(enabled).c_str());
+  DisplayError error = kErrorNone;
+
+  if (shutdown_pending_ || !callbacks_->VsyncCallbackRegistered()) {
+    return HWC2::Error::None;
+  }
+
+  bool state;
+  if (enabled == HWC2::Vsync::Enable)
+    state = true;
+  else if (enabled == HWC2::Vsync::Disable)
+    state = false;
+  else
+    return HWC2::Error::BadParameter;
+
+  error = display_intf_->SetVSyncState(state);
+
+  if (error != kErrorNone) {
+    if (error == kErrorShutDown) {
+      shutdown_pending_ = true;
+      return HWC2::Error::None;
+    }
+    DLOGE("Failed. enabled = %s, error = %d", to_string(enabled).c_str(), error);
+    return HWC2::Error::BadDisplay;
+  }
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::SetPowerMode(HWC2::PowerMode mode) {
+  DLOGV("display = %d, mode = %s", id_, to_string(mode).c_str());
+  DisplayState state = kStateOff;
+  bool flush_on_error = flush_on_error_;
+
+  if (shutdown_pending_) {
+    return HWC2::Error::None;
+  }
+
+  switch (mode) {
+    case HWC2::PowerMode::Off:
+      // During power off, all of the buffers are released.
+      // Do not flush until a buffer is successfully submitted again.
+      flush_on_error = false;
+      state = kStateOff;
+      if (tone_mapper_) {
+        tone_mapper_->Terminate();
+      }
+      break;
+    case HWC2::PowerMode::On:
+      state = kStateOn;
+      last_power_mode_ = HWC2::PowerMode::On;
+      break;
+    case HWC2::PowerMode::Doze:
+      state = kStateDoze;
+      last_power_mode_ = HWC2::PowerMode::Doze;
+      break;
+    case HWC2::PowerMode::DozeSuspend:
+      state = kStateDozeSuspend;
+      last_power_mode_ = HWC2::PowerMode::DozeSuspend;
+      break;
+    default:
+      return HWC2::Error::BadParameter;
+  }
+
+  DisplayError error = display_intf_->SetDisplayState(state);
+  if (error == kErrorNone) {
+    flush_on_error_ = flush_on_error;
+  } else {
+    if (error == kErrorShutDown) {
+      shutdown_pending_ = true;
+      return HWC2::Error::None;
+    }
+    DLOGE("Set state failed. Error = %d", error);
+    return HWC2::Error::BadParameter;
+  }
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetClientTargetSupport(uint32_t width, uint32_t height, int32_t format,
+                                               int32_t dataspace) {
+  DisplayConfigVariableInfo variable_config;
+  display_intf_->GetFrameBufferConfig(&variable_config);
+  // TODO(user): Support scaled configurations, other formats and other dataspaces
+  if (format != HAL_PIXEL_FORMAT_RGBA_8888 || dataspace != HAL_DATASPACE_UNKNOWN ||
+      width != variable_config.x_pixels || height != variable_config.y_pixels) {
+    return HWC2::Error::Unsupported;
+  } else {
+    return HWC2::Error::None;
+  }
+}
+
+HWC2::Error HWCDisplay::GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes) {
+  if (out_modes) {
+    out_modes[0] = HAL_COLOR_MODE_NATIVE;
+  }
+  *out_num_modes = 1;
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs) {
+  // TODO(user): Actually handle multiple configs
+  if (out_configs == nullptr) {
+    *out_num_configs = 1;
+  } else {
+    *out_num_configs = 1;
+    out_configs[0] = 0;
+  }
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
+                                            int32_t *out_value) {
+  DisplayConfigVariableInfo variable_config;
+  DisplayError error = display_intf_->GetFrameBufferConfig(&variable_config);
+  if (error != kErrorNone) {
+    DLOGV("Get variable config failed. Error = %d", error);
+    return HWC2::Error::BadDisplay;
+  }
+
+  if (config != 0) {  // We only use config[0] - see TODO above
+      return HWC2::Error::BadConfig;
+  }
+
+  switch (attribute) {
+    case HWC2::Attribute::VsyncPeriod:
+      *out_value = INT32(variable_config.vsync_period_ns);
+      break;
+    case HWC2::Attribute::Width:
+      *out_value = INT32(variable_config.x_pixels);
+      break;
+    case HWC2::Attribute::Height:
+      *out_value = INT32(variable_config.y_pixels);
+      break;
+    case HWC2::Attribute::DpiX:
+      *out_value = INT32(variable_config.x_dpi * 1000.0f);
+      break;
+    case HWC2::Attribute::DpiY:
+      *out_value = INT32(variable_config.y_dpi * 1000.0f);
+      break;
+    default:
+      DLOGW("Spurious attribute type = %s", to_string(attribute).c_str());
+      *out_value = -1;
+      return HWC2::Error::BadConfig;
+  }
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetDisplayName(uint32_t *out_size, char *out_name) {
+  // TODO(user): Get panel name and EDID name and populate it here
+  if (out_name == nullptr) {
+    *out_size = 32;
+  } else {
+    std::string name;
+    switch (id_) {
+      case HWC_DISPLAY_PRIMARY:
+        name = "Primary Display";
+        break;
+      case HWC_DISPLAY_EXTERNAL:
+        name = "External Display";
+        break;
+      case HWC_DISPLAY_VIRTUAL:
+        name = "Virtual Display";
+        break;
+      default:
+        name = "Unknown";
+        break;
+    }
+    std::strncpy(out_name, name.c_str(), name.size());
+    *out_size = UINT32(name.size());
+  }
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetDisplayType(int32_t *out_type) {
+  if (out_type != nullptr) {
+    if (id_ == HWC_DISPLAY_VIRTUAL) {
+      *out_type = HWC2_DISPLAY_TYPE_VIRTUAL;
+    } else {
+      *out_type = HWC2_DISPLAY_TYPE_PHYSICAL;
+    }
+    return HWC2::Error::None;
+  } else {
+    return HWC2::Error::BadParameter;
+  }
+}
+
+// TODO(user): Store configurations and hook them up here
+HWC2::Error HWCDisplay::GetActiveConfig(hwc2_config_t *out_config) {
+  if (out_config != nullptr) {
+    *out_config = 0;
+    return HWC2::Error::None;
+  } else {
+    return HWC2::Error::BadParameter;
+  }
+}
+
+HWC2::Error HWCDisplay::SetClientTarget(buffer_handle_t target, int32_t acquire_fence,
+                                        int32_t dataspace, hwc_region_t damage) {
+  // TODO(user): SurfaceFlinger gives us a null pointer here when doing full SDE composition
+  // The error is problematic for layer caching as it would overwrite our cached client target.
+  // Reported bug 28569722 to resolve this.
+  // For now, continue to use the last valid buffer reported to us for layer caching.
+  if (target == nullptr) {
+    return HWC2::Error::None;
+  }
+
+  if (acquire_fence == 0) {
+    DLOGE("acquire_fence is zero");
+    return HWC2::Error::BadParameter;
+  }
+
+  client_target_->SetLayerBuffer(target, acquire_fence);
+  client_target_->SetLayerSurfaceDamage(damage);
+  // Ignoring dataspace for now
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::SetActiveConfig(hwc2_config_t config) {
+  if (config != 0) {
+    return HWC2::Error::BadConfig;
+  }
+  // We have only one config right now - do nothing
+  return HWC2::Error::None;
+}
+
+DisplayError HWCDisplay::SetMixerResolution(uint32_t width, uint32_t height) {
+  return kErrorNotSupported;
+}
+
+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);
+
+  if (tone_mapper_) {
+    tone_mapper_->SetFrameDumpConfig(count);
+  }
+
+  DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
+}
+
+HWC2::PowerMode HWCDisplay::GetLastPowerMode() {
+  return last_power_mode_;
+}
+
+DisplayError HWCDisplay::VSync(const DisplayEventVSync &vsync) {
+  callbacks_->Vsync(id_, vsync.timestamp);
+  return kErrorNone;
+}
+
+DisplayError HWCDisplay::Refresh() {
+  return kErrorNotSupported;
+}
+
+DisplayError HWCDisplay::CECMessage(char *message) {
+  if (qservice_) {
+    qservice_->onCECMessageReceived(message, 0);
+  } else {
+    DLOGW("Qservice instance not available.");
+  }
+
+  return kErrorNone;
+}
+
+HWC2::Error HWCDisplay::PrepareLayerStack(uint32_t *out_num_types, uint32_t *out_num_requests) {
+  layer_changes_.clear();
+  layer_requests_.clear();
+  if (shutdown_pending_) {
+    return HWC2::Error::BadDisplay;
+  }
+
+  if (!skip_prepare_) {
+    DisplayError error = display_intf_->Prepare(&layer_stack_);
+    if (error != kErrorNone) {
+      if (error == kErrorShutDown) {
+        shutdown_pending_ = true;
+      } else if (error != kErrorPermission) {
+        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 HWC2::Error::BadDisplay;
+    }
+  } else {
+    // Skip is not set
+    MarkLayersForGPUBypass();
+    skip_prepare_ = false;
+    DLOGI("SecureDisplay %s, Skip Prepare/Commit and Flush",
+          secure_display_active_ ? "Starting" : "Stopping");
+    flush_ = true;
+  }
+
+  for (auto hwc_layer : layer_set_) {
+    Layer *layer = hwc_layer->GetSDMLayer();
+    LayerComposition &composition = layer->composition;
+
+    if ((composition == kCompositionSDE) || (composition == kCompositionHybrid) ||
+        (composition == kCompositionBlit)) {
+      layer_requests_[hwc_layer->GetId()] = HWC2::LayerRequest::ClearClientTarget;
+    }
+
+    HWC2::Composition requested_composition = hwc_layer->GetClientRequestedCompositionType();
+    // Set SDM composition to HWC2 type in HWCLayer
+    hwc_layer->SetComposition(composition);
+    HWC2::Composition device_composition  = hwc_layer->GetDeviceSelectedCompositionType();
+    // Update the changes list only if the requested composition is different from SDM comp type
+    // TODO(user): Take Care of other comptypes(BLIT)
+    if (requested_composition != device_composition) {
+      layer_changes_[hwc_layer->GetId()] = device_composition;
+    }
+  }
+  *out_num_types = UINT32(layer_changes_.size());
+  *out_num_requests = UINT32(layer_requests_.size());
+  validated_ = true;
+  if (*out_num_types > 0) {
+    return HWC2::Error::HasChanges;
+  } else {
+    return HWC2::Error::None;
+  }
+}
+
+HWC2::Error HWCDisplay::AcceptDisplayChanges() {
+  if (layer_set_.empty()) {
+    return HWC2::Error::None;
+  }
+
+  if (!validated_) {
+    return HWC2::Error::NotValidated;
+  }
+
+  for (const auto& change : layer_changes_) {
+    auto hwc_layer = layer_map_[change.first];
+    auto composition = change.second;
+    if (hwc_layer != nullptr) {
+      hwc_layer->UpdateClientCompositionType(composition);
+    } else {
+      DLOGW("Invalid layer: %" PRIu64, change.first);
+    }
+  }
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetChangedCompositionTypes(uint32_t *out_num_elements,
+                                                   hwc2_layer_t *out_layers, int32_t *out_types) {
+  if (layer_set_.empty()) {
+    return HWC2::Error::None;
+  }
+
+  if (!validated_) {
+    DLOGW("Display is not validated");
+    return HWC2::Error::NotValidated;
+  }
+  *out_num_elements = UINT32(layer_changes_.size());
+  if (out_layers != nullptr && out_types != nullptr) {
+    int i = 0;
+    for (auto change : layer_changes_) {
+      out_layers[i] = change.first;
+      out_types[i] = INT32(change.second);
+      i++;
+    }
+  }
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetReleaseFences(uint32_t *out_num_elements, hwc2_layer_t *out_layers,
+                                         int32_t *out_fences) {
+  if (out_layers != nullptr && out_fences != nullptr) {
+    int i = 0;
+    for (auto hwc_layer : layer_set_) {
+      out_layers[i] = hwc_layer->GetId();
+      out_fences[i] = hwc_layer->PopReleaseFence();
+      i++;
+    }
+  }
+  *out_num_elements = UINT32(layer_set_.size());
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetDisplayRequests(int32_t *out_display_requests,
+                                           uint32_t *out_num_elements, hwc2_layer_t *out_layers,
+                                           int32_t *out_layer_requests) {
+  // No display requests for now
+  // Use for sharing blit buffers and
+  // writing wfd buffer directly to output if there is full GPU composition
+  // and no color conversion needed
+  if (layer_set_.empty()) {
+    return HWC2::Error::None;
+  }
+
+  if (!validated_) {
+    DLOGW("Display is not validated");
+    return HWC2::Error::NotValidated;
+  }
+  *out_display_requests = 0;
+  *out_num_elements = UINT32(layer_requests_.size());
+  if (out_layers != nullptr && out_layer_requests != nullptr) {
+    int i = 0;
+    for (auto &request : layer_requests_) {
+      out_layers[i] = request.first;
+      out_layer_requests[i] = INT32(request.second);
+      i++;
+    }
+  }
+
+  auto client_target_layer = client_target_->GetSDMLayer();
+  if (client_target_layer->request.flags.flip_buffer) {
+    *out_display_requests = INT32(HWC2::DisplayRequest::FlipClientTarget);
+  }
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::GetHdrCapabilities(uint32_t *out_num_types, int32_t *out_types,
+                                           float *out_max_luminance,
+                                           float *out_max_average_luminance,
+                                           float *out_min_luminance) {
+  DisplayConfigFixedInfo fixed_info = {};
+  display_intf_->GetConfig(&fixed_info);
+
+  if (!fixed_info.hdr_supported) {
+    *out_num_types = 0;
+    DLOGI("HDR is not supported");
+    return HWC2::Error::None;
+  }
+
+  if (out_types == nullptr) {
+    // 1(now) - because we support only HDR10, change when HLG & DOLBY vision are supported
+    *out_num_types  = 1;
+  } else {
+    // Only HDR10 supported
+    *out_types = HAL_HDR_HDR10;
+    static const float kLuminanceFactor = 10000.0;
+    // luminance is expressed in the unit of 0.0001 cd/m2, convert it to 1cd/m2.
+    *out_max_luminance = FLOAT(fixed_info.max_luminance)/kLuminanceFactor;
+    *out_max_average_luminance = FLOAT(fixed_info.average_luminance)/kLuminanceFactor;
+    *out_min_luminance = FLOAT(fixed_info.min_luminance)/kLuminanceFactor;
+  }
+
+  return HWC2::Error::None;
+}
+
+
+HWC2::Error HWCDisplay::CommitLayerStack(void) {
+  if (shutdown_pending_ || layer_set_.empty()) {
+    return HWC2::Error::None;
+  }
+
+  if (!validated_) {
+    DLOGW("Display is not validated");
+    return HWC2::Error::NotValidated;
+  }
+
+  DumpInputBuffers();
+
+  if (!flush_) {
+    DisplayError error = kErrorUndefined;
+    int status = 0;
+    if (tone_mapper_) {
+      if (layer_stack_.flags.hdr_present) {
+        status = tone_mapper_->HandleToneMap(&layer_stack_);
+        if (status != 0) {
+          DLOGE("Error handling HDR in ToneMapper");
+        }
+      } else {
+        tone_mapper_->Terminate();
+      }
+    }
+    error = display_intf_->Commit(&layer_stack_);
+    validated_ = false;
+
+    if (error == kErrorNone) {
+      // A commit is successfully submitted, start flushing on failure now onwards.
+      flush_on_error_ = true;
+    } else {
+      if (error == kErrorShutDown) {
+        shutdown_pending_ = true;
+        return HWC2::Error::Unsupported;
+      } else if (error != kErrorPermission) {
+        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 HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplay::PostCommitLayerStack(int32_t *out_retire_fence) {
+  auto status = HWC2::Error::None;
+
+  // Do no call flush on errors, if a successful buffer is never submitted.
+  if (flush_ && flush_on_error_) {
+    display_intf_->Flush();
+  }
+
+  if (tone_mapper_ && tone_mapper_->IsActive()) {
+     tone_mapper_->PostCommit(&layer_stack_);
+  }
+
+  // TODO(user): No way to set the client target release fence on SF
+  int32_t &client_target_release_fence =
+      client_target_->GetSDMLayer()->input_buffer.release_fence_fd;
+  if (client_target_release_fence >= 0) {
+    close(client_target_release_fence);
+    client_target_release_fence = -1;
+  }
+
+  for (auto hwc_layer : layer_set_) {
+    hwc_layer->ResetGeometryChanges();
+    Layer *layer = hwc_layer->GetSDMLayer();
+    LayerBuffer *layer_buffer = &layer->input_buffer;
+
+    if (!flush_) {
+      // If swapinterval property is set to 0 or for single buffer layers, do not update f/w
+      // release fences and discard fences from driver
+      if (swap_interval_zero_ || layer->flags.single_buffer) {
+        close(layer_buffer->release_fence_fd);
+        layer_buffer->release_fence_fd = -1;
+      } else if (layer->composition != kCompositionGPU) {
+        hwc_layer->PushReleaseFence(layer_buffer->release_fence_fd);
+        layer_buffer->release_fence_fd = -1;
+      } else {
+        hwc_layer->PushReleaseFence(-1);
+      }
+    }
+
+    if (layer_buffer->acquire_fence_fd >= 0) {
+      close(layer_buffer->acquire_fence_fd);
+      layer_buffer->acquire_fence_fd = -1;
+    }
+  }
+
+  *out_retire_fence = -1;
+  if (!flush_) {
+    // 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;
+    }
+    *out_retire_fence = layer_stack_.retire_fence_fd;
+
+    if (dump_frame_count_) {
+      dump_frame_count_--;
+      dump_frame_index_++;
+    }
+  }
+
+  geometry_changes_ = GeometryChanges::kNone;
+  flush_ = false;
+
+  ClearRequestFlags();
+
+  return status;
+}
+
+void HWCDisplay::SetIdleTimeoutMs(uint32_t timeout_ms) {
+  return;
+}
+
+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_BGR_565:
+        format = kFormatBGR565Ubwc;
+        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;
+      case HAL_PIXEL_FORMAT_RGBA_1010102:
+        format = kFormatRGBA1010102Ubwc;
+        break;
+      case HAL_PIXEL_FORMAT_RGBX_1010102:
+        format = kFormatRGBX1010102Ubwc;
+        break;
+      case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+        format = kFormatYCbCr420TP10Ubwc;
+        break;
+      case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+        format = kFormatYCbCr420P010Ubwc;
+        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_BGR_565:
+      format = kFormatBGR565;
+      break;
+    case HAL_PIXEL_FORMAT_BGR_888:
+      format = kFormatBGR888;
+      break;
+    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+      format = kFormatYCbCr420SemiPlanarVenus;
+      break;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+      format = kFormatYCrCb420SemiPlanarVenus;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+      format = kFormatYCbCr420SPVenusUbwc;
+      break;
+    case HAL_PIXEL_FORMAT_YV12:
+      format = kFormatYCrCb420PlanarStride16;
+      break;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+      format = kFormatYCrCb420SemiPlanar;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+      format = kFormatYCbCr420SemiPlanar;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+      format = kFormatYCbCr422H2V1SemiPlanar;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_422_I:
+      format = kFormatYCbCr422H2V1Packed;
+      break;
+    case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+      format = kFormatCbYCrY422H2V1Packed;
+      break;
+    case HAL_PIXEL_FORMAT_RGBA_1010102:
+      format = kFormatRGBA1010102;
+      break;
+    case HAL_PIXEL_FORMAT_ARGB_2101010:
+      format = kFormatARGB2101010;
+      break;
+    case HAL_PIXEL_FORMAT_RGBX_1010102:
+      format = kFormatRGBX1010102;
+      break;
+    case HAL_PIXEL_FORMAT_XRGB_2101010:
+      format = kFormatXRGB2101010;
+      break;
+    case HAL_PIXEL_FORMAT_BGRA_1010102:
+      format = kFormatBGRA1010102;
+      break;
+    case HAL_PIXEL_FORMAT_ABGR_2101010:
+      format = kFormatABGR2101010;
+      break;
+    case HAL_PIXEL_FORMAT_BGRX_1010102:
+      format = kFormatBGRX1010102;
+      break;
+    case HAL_PIXEL_FORMAT_XBGR_2101010:
+      format = kFormatXBGR2101010;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+      format = kFormatYCbCr420P010;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+      format = kFormatYCbCr420TP10Ubwc;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+      format = kFormatYCbCr420P010Ubwc;
+      break;
+    default:
+      DLOGW("Unsupported format type = %d", source);
+      return kFormatInvalid;
+  }
+
+  return format;
+}
+
+void HWCDisplay::DumpInputBuffers() {
+  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 < layer_stack_.layers.size(); i++) {
+    auto layer = layer_stack_.layers.at(i);
+    const private_handle_t *pvt_handle =
+        reinterpret_cast<const private_handle_t *>(layer->input_buffer.buffer_id);
+    auto acquire_fence_fd = layer->input_buffer.acquire_fence_fd;
+
+    if (acquire_fence_fd >= 0) {
+      int error = sync_wait(acquire_fence_fd, 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,
+               qdutils::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");
+    }
+  }
+}
+
+void HWCDisplay::DumpOutputBuffer(const BufferInfo &buffer_info, void *base, int fence) {
+  char dir_path[PATH_MAX];
+
+  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 (base) {
+    char dump_file_name[PATH_MAX];
+    size_t result = 0;
+
+    if (fence >= 0) {
+      int error = sync_wait(fence, 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, buffer_info.buffer_config.width, buffer_info.buffer_config.height,
+             GetFormatString(buffer_info.buffer_config.format), dump_frame_index_);
+
+    FILE *fp = fopen(dump_file_name, "w+");
+    if (fp) {
+      result = fwrite(base, buffer_info.alloc_buffer_info.size, 1, fp);
+      fclose(fp);
+    }
+
+    DLOGI("Frame Dump of %s is %s", dump_file_name, result ? "Successful" : "Failed");
+  }
+}
+
+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) {
+    DLOGW("Unsupported config: x_pixels=%d, y_pixels=%d", x_pixels, y_pixels);
+    return -EINVAL;
+  }
+
+  DisplayConfigVariableInfo fb_config;
+  DisplayError error = display_intf_->GetFrameBufferConfig(&fb_config);
+  if (error != kErrorNone) {
+    DLOGV("Get frame buffer config failed. Error = %d", error);
+    return -EINVAL;
+  }
+
+  fb_config.x_pixels = x_pixels;
+  fb_config.y_pixels = y_pixels;
+
+  error = display_intf_->SetFrameBufferConfig(fb_config);
+  if (error != kErrorNone) {
+    DLOGV("Set frame buffer config failed. Error = %d", error);
+    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(fb_config.x_pixels), FLOAT(fb_config.y_pixels));
+  auto client_target_layer = client_target_->GetSDMLayer();
+  client_target_layer->src_rect = crop;
+  client_target_layer->dst_rect = dst;
+
+  int aligned_width;
+  int aligned_height;
+  uint32_t usage = GRALLOC_USAGE_HW_FB;
+  int format = HAL_PIXEL_FORMAT_RGBA_8888;
+  int ubwc_enabled = 0;
+  int flags = 0;
+  HWCDebugHandler::Get()->GetProperty("debug.gralloc.enable_fb_ubwc", &ubwc_enabled);
+  if (ubwc_enabled == 1) {
+    usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+  }
+
+#ifdef USE_GRALLOC1
+  buffer_allocator_->GetAlignedWidthAndHeight(INT(x_pixels), INT(y_pixels), format, usage,
+                                              &aligned_width, &aligned_height);
+#else
+  AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(INT(x_pixels), INT(y_pixels), format,
+                                                        INT(usage), aligned_width, aligned_height);
+#endif
+
+  // TODO(user): How does the dirty region get set on the client target? File bug on Google
+  client_target_layer->composition = kCompositionGPUTarget;
+  client_target_layer->input_buffer.format = GetSDMFormat(format, flags);
+  client_target_layer->input_buffer.width = UINT32(aligned_width);
+  client_target_layer->input_buffer.height = UINT32(aligned_height);
+  client_target_layer->input_buffer.unaligned_width = x_pixels;
+  client_target_layer->input_buffer.unaligned_height = y_pixels;
+  client_target_layer->plane_alpha = 255;
+
+  DLOGI("New framebuffer resolution (%dx%d)", fb_config.x_pixels, fb_config.y_pixels);
+
+  return 0;
+}
+
+void HWCDisplay::GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+  DisplayConfigVariableInfo fb_config;
+  display_intf_->GetFrameBufferConfig(&fb_config);
+
+  *x_pixels = fb_config.x_pixels;
+  *y_pixels = fb_config.y_pixels;
+}
+
+DisplayError HWCDisplay::GetMixerResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+  return display_intf_->GetMixerResolution(x_pixels, y_pixels);
+}
+
+void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+  DisplayConfigVariableInfo display_config;
+  uint32_t active_index = 0;
+
+  display_intf_->GetActiveConfig(&active_index);
+  display_intf_->GetConfig(active_index, &display_config);
+
+  *x_pixels = display_config.x_pixels;
+  *y_pixels = display_config.y_pixels;
+}
+
+int HWCDisplay::SetDisplayStatus(uint32_t display_status) {
+  int status = 0;
+
+  switch (display_status) {
+    case kDisplayStatusResume:
+      display_paused_ = false;
+    case kDisplayStatusOnline:
+      status = INT32(SetPowerMode(HWC2::PowerMode::On));
+      break;
+    case kDisplayStatusPause:
+      display_paused_ = true;
+    case kDisplayStatusOffline:
+      status = INT32(SetPowerMode(HWC2::PowerMode::Off));
+      break;
+    default:
+      DLOGW("Invalid display status %d", display_status);
+      return -EINVAL;
+  }
+
+  if (display_status == kDisplayStatusResume || display_status == kDisplayStatusPause) {
+    callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+  }
+
+  return status;
+}
+
+HWC2::Error HWCDisplay::SetCursorPosition(hwc2_layer_t layer, int x, int y) {
+  if (shutdown_pending_) {
+    return HWC2::Error::None;
+  }
+
+  if (GetHWCLayer(layer) == nullptr) {
+    return HWC2::Error::BadLayer;
+  }
+
+  DisplayState state;
+  if (display_intf_->GetDisplayState(&state) == kErrorNone) {
+    if (state != kStateOn) {
+      return HWC2::Error::None;
+    }
+  }
+
+  if (!validated_) {
+    return HWC2::Error::NotValidated;
+  }
+
+  auto error = display_intf_->SetCursorPosition(x, y);
+  if (error != kErrorNone) {
+    if (error == kErrorShutDown) {
+      shutdown_pending_ = true;
+      return HWC2::Error::None;
+    }
+
+    DLOGE("Failed for x = %d y = %d, Error = %d", x, y, error);
+    return HWC2::Error::BadDisplay;
+  }
+
+  return HWC2::Error::None;
+}
+
+int HWCDisplay::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
+  DisplayError error = display_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
+  if (error != kErrorNone) {
+    DLOGE("Failed. Error = %d", error);
+    return -1;
+  }
+
+  return 0;
+}
+
+void HWCDisplay::MarkLayersForGPUBypass() {
+  for (auto hwc_layer : layer_set_) {
+    auto layer = hwc_layer->GetSDMLayer();
+    layer->composition = kCompositionSDE;
+  }
+}
+
+void HWCDisplay::MarkLayersForClientComposition() {
+  // ClientComposition - GPU comp, to acheive this, set skip flag so that
+  // SDM does not handle this layer and hwc_layer composition will be
+  // set correctly at the end of Prepare.
+  for (auto hwc_layer : layer_set_) {
+    Layer *layer = hwc_layer->GetSDMLayer();
+    layer->flags.skip = true;
+  }
+}
+
+void HWCDisplay::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+}
+
+int HWCDisplay::SetPanelBrightness(int level) {
+  int ret = 0;
+  if (display_intf_)
+    ret = display_intf_->SetPanelBrightness(level);
+  else
+    ret = -EINVAL;
+
+  return ret;
+}
+
+int HWCDisplay::GetPanelBrightness(int *level) {
+  return display_intf_->GetPanelBrightness(level);
+}
+
+int HWCDisplay::ToggleScreenUpdates(bool enable) {
+  display_paused_ = enable ? false : true;
+  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+  return 0;
+}
+
+int HWCDisplay::ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
+                                     PPDisplayAPIPayload *out_payload,
+                                     PPPendingParams *pending_action) {
+  int ret = 0;
+
+  if (display_intf_)
+    ret = display_intf_->ColorSVCRequestRoute(in_payload, out_payload, pending_action);
+  else
+    ret = -EINVAL;
+
+  return ret;
+}
+
+void HWCDisplay::SolidFillPrepare() {
+  if (solid_fill_enable_) {
+    if (solid_fill_layer_ == NULL) {
+      // Create a dummy layer here
+      solid_fill_layer_ = new Layer();
+    }
+    uint32_t primary_width = 0, primary_height = 0;
+    GetMixerResolution(&primary_width, &primary_height);
+
+    LayerBuffer *layer_buffer = &solid_fill_layer_->input_buffer;
+    layer_buffer->width = primary_width;
+    layer_buffer->height = primary_height;
+    layer_buffer->unaligned_width = primary_width;
+    layer_buffer->unaligned_height = primary_height;
+    layer_buffer->acquire_fence_fd = -1;
+    layer_buffer->release_fence_fd = -1;
+
+    LayerRect rect;
+    rect.top = 0; rect.left = 0;
+    rect.right = primary_width;
+    rect.bottom = primary_height;
+
+    solid_fill_layer_->composition = kCompositionGPU;
+    solid_fill_layer_->src_rect = rect;
+    solid_fill_layer_->dst_rect = rect;
+
+    solid_fill_layer_->blending = kBlendingPremultiplied;
+    solid_fill_layer_->solid_fill_color = solid_fill_color_;
+    solid_fill_layer_->frame_rate = 60;
+    solid_fill_layer_->visible_regions.push_back(solid_fill_layer_->dst_rect);
+    solid_fill_layer_->flags.updating = 1;
+    solid_fill_layer_->flags.solid_fill = true;
+  } else {
+    // delete the dummy layer
+    delete solid_fill_layer_;
+    solid_fill_layer_ = NULL;
+  }
+
+  if (solid_fill_enable_ && solid_fill_layer_) {
+    BuildSolidFillStack();
+    MarkLayersForGPUBypass();
+  }
+
+  return;
+}
+
+void HWCDisplay::SolidFillCommit() {
+  if (solid_fill_enable_ && solid_fill_layer_) {
+    LayerBuffer *layer_buffer = &solid_fill_layer_->input_buffer;
+    if (layer_buffer->release_fence_fd > 0) {
+      close(layer_buffer->release_fence_fd);
+      layer_buffer->release_fence_fd = -1;
+    }
+    if (layer_stack_.retire_fence_fd > 0) {
+      close(layer_stack_.retire_fence_fd);
+      layer_stack_.retire_fence_fd = -1;
+    }
+  }
+}
+
+int HWCDisplay::GetVisibleDisplayRect(hwc_rect_t *visible_rect) {
+  if (!IsValid(display_rect_)) {
+    return -EINVAL;
+  }
+
+  visible_rect->left = INT(display_rect_.left);
+  visible_rect->top = INT(display_rect_.top);
+  visible_rect->right = INT(display_rect_.right);
+  visible_rect->bottom = INT(display_rect_.bottom);
+  DLOGI("Dpy = %d Visible Display Rect(%d %d %d %d)", visible_rect->left, visible_rect->top,
+        visible_rect->right, visible_rect->bottom);
+
+  return 0;
+}
+
+void HWCDisplay::SetSecureDisplay(bool secure_display_active) {
+  secure_display_active_ = secure_display_active;
+  return;
+}
+
+int HWCDisplay::SetActiveDisplayConfig(int config) {
+  return display_intf_->SetActiveConfig(UINT32(config)) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetActiveDisplayConfig(uint32_t *config) {
+  return display_intf_->GetActiveConfig(config) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetDisplayConfigCount(uint32_t *count) {
+  return display_intf_->GetNumVariableInfoConfigs(count) == kErrorNone ? 0 : -1;
+}
+
+int HWCDisplay::GetDisplayAttributesForConfig(int config,
+                                            DisplayConfigVariableInfo *display_attributes) {
+  return display_intf_->GetConfig(UINT32(config), display_attributes) == kErrorNone ? 0 : -1;
+}
+
+bool HWCDisplay::SingleLayerUpdating(void) {
+  uint32_t updating_count = 0;
+
+  for (uint i = 0; i < layer_stack_.layers.size(); i++) {
+    auto layer = layer_stack_.layers.at(i);
+    if (layer->flags.updating) {
+      updating_count++;
+    }
+  }
+
+  return (updating_count == 1);
+}
+
+bool HWCDisplay::IsLayerUpdating(const Layer *layer) {
+  // Layer should be considered updating if
+  //   a) layer is in single buffer mode, or
+  //   b) valid dirty_regions(android specific hint for updating status), or
+  //   c) layer stack geometry has changed (TODO(user): Remove when SDM accepts
+  //      geometry_changed as bit fields).
+  return (layer->flags.single_buffer || IsSurfaceUpdated(layer->dirty_regions) ||
+          geometry_changes_);
+}
+
+bool HWCDisplay::IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions) {
+  // based on dirty_regions determine if its updating
+  // dirty_rect count = 0 - whole layer - updating.
+  // dirty_rect count = 1 or more valid rects - updating.
+  // dirty_rect count = 1 with (0,0,0,0) - not updating.
+  return (dirty_regions.empty() || IsValid(dirty_regions.at(0)));
+}
+
+uint32_t HWCDisplay::SanitizeRefreshRate(uint32_t req_refresh_rate) {
+  uint32_t refresh_rate = req_refresh_rate;
+
+  if (refresh_rate < min_refresh_rate_) {
+    // Pick the next multiple of request which is within the range
+    refresh_rate =
+        (((min_refresh_rate_ / refresh_rate) + ((min_refresh_rate_ % refresh_rate) ? 1 : 0)) *
+         refresh_rate);
+  }
+
+  if (refresh_rate > max_refresh_rate_) {
+    refresh_rate = max_refresh_rate_;
+  }
+
+  return refresh_rate;
+}
+
+DisplayClass HWCDisplay::GetDisplayClass() {
+  return display_class_;
+}
+
+void HWCDisplay::CloseAcquireFds() {
+  for (auto hwc_layer : layer_set_) {
+    auto layer = hwc_layer->GetSDMLayer();
+    if (layer->input_buffer.acquire_fence_fd >= 0) {
+      close(layer->input_buffer.acquire_fence_fd);
+      layer->input_buffer.acquire_fence_fd = -1;
+    }
+  }
+  int32_t &client_target_acquire_fence =
+      client_target_->GetSDMLayer()->input_buffer.acquire_fence_fd;
+  if (client_target_acquire_fence >= 0) {
+    close(client_target_acquire_fence);
+    client_target_acquire_fence = -1;
+  }
+}
+
+void HWCDisplay::ClearRequestFlags() {
+  for (Layer *layer : layer_stack_.layers) {
+    layer->request.flags = {};
+  }
+}
+
+std::string HWCDisplay::Dump() {
+  std::ostringstream os;
+  os << "-------------------------------" << std::endl;
+  os << "HWC2 display_id: " << id_ << std::endl;
+  for (auto layer : layer_set_) {
+    auto sdm_layer = layer->GetSDMLayer();
+    auto transform = sdm_layer->transform;
+    os << "layer: " << std::setw(4) << layer->GetId();
+    os << " z: " << layer->GetZ();
+    os << " compositon: " <<
+          to_string(layer->GetClientRequestedCompositionType()).c_str();
+    os << "/" <<
+          to_string(layer->GetDeviceSelectedCompositionType()).c_str();
+    os << " alpha: " << std::to_string(sdm_layer->plane_alpha).c_str();
+    os << " format: " << std::setw(22) << GetFormatString(sdm_layer->input_buffer.format);
+    os << " dataspace:" << std::hex << "0x" << std::setw(8) << std::setfill('0')
+       << layer->GetLayerDataspace() << std::dec << std::setfill(' ');
+    os << " transform: " << transform.rotation << "/" << transform.flip_horizontal <<
+          "/"<< transform.flip_vertical;
+    os << " buffer_id: " << std::hex << "0x" << sdm_layer->input_buffer.buffer_id << std::dec
+       << std::endl;
+  }
+  if (color_mode_) {
+    color_mode_->Dump(&os);
+  }
+  os << "-------------------------------" << std::endl;
+  return os.str();
+}
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc2/hwc_display.h b/sdm845/sdm/libs/hwc2/hwc_display.h
new file mode 100644
index 0000000..1b04c84
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_display.h
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HWC_DISPLAY_H__
+#define __HWC_DISPLAY_H__
+
+#include <QService.h>
+#include <core/core_interface.h>
+#include <hardware/hwcomposer.h>
+#include <private/color_params.h>
+#include <qdMetaData.h>
+#include <map>
+#include <queue>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "hwc_buffer_allocator.h"
+#include "hwc_callbacks.h"
+#include "hwc_layers.h"
+
+namespace sdm {
+
+class BlitEngine;
+class HWCToneMapper;
+
+// Subclasses set this to their type. This has to be different from DisplayType.
+// This is to avoid RTTI and dynamic_cast
+enum DisplayClass {
+  DISPLAY_CLASS_PRIMARY,
+  DISPLAY_CLASS_EXTERNAL,
+  DISPLAY_CLASS_VIRTUAL,
+  DISPLAY_CLASS_NULL
+};
+
+class HWCColorMode {
+ public:
+  explicit HWCColorMode(DisplayInterface *display_intf);
+  ~HWCColorMode() {}
+  HWC2::Error Init();
+  HWC2::Error DeInit();
+  void Dump(std::ostringstream* os);
+  uint32_t GetColorModeCount();
+  HWC2::Error GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes);
+  HWC2::Error SetColorMode(android_color_mode_t mode);
+  HWC2::Error SetColorModeById(int32_t color_mode_id);
+  HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint);
+
+ private:
+  static const uint32_t kColorTransformMatrixCount = 16;
+
+  HWC2::Error HandleColorModeTransform(android_color_mode_t mode,
+                                       android_color_transform_t hint, const double *matrix);
+  void PopulateColorModes();
+  void PopulateTransform(const android_color_mode_t &mode,
+                         const std::string &color_mode, const std::string &color_transform);
+  template <class T>
+  void CopyColorTransformMatrix(const T *input_matrix, double *output_matrix) {
+    for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
+      output_matrix[i] = static_cast<double>(input_matrix[i]);
+    }
+  }
+  HWC2::Error ApplyDefaultColorMode();
+
+  DisplayInterface *display_intf_ = NULL;
+  android_color_mode_t current_color_mode_ = HAL_COLOR_MODE_NATIVE;
+  android_color_transform_t current_color_transform_ = HAL_COLOR_TRANSFORM_IDENTITY;
+  typedef std::map<android_color_transform_t, std::string> TransformMap;
+  std::map<android_color_mode_t, TransformMap> color_mode_transform_map_ = {};
+  double color_matrix_[kColorTransformMatrixCount] = { 1.0, 0.0, 0.0, 0.0, \
+                                                       0.0, 1.0, 0.0, 0.0, \
+                                                       0.0, 0.0, 1.0, 0.0, \
+                                                       0.0, 0.0, 0.0, 1.0 };
+};
+
+class HWCDisplay : public DisplayEventHandler {
+ public:
+  virtual ~HWCDisplay() {}
+  virtual int Init();
+  virtual int Deinit();
+
+  // Framebuffer configurations
+  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 DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) {
+    return kErrorNotSupported;
+  }
+  virtual HWC2::PowerMode GetLastPowerMode();
+  virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels);
+  virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels);
+  virtual int SetDisplayStatus(uint32_t display_status);
+  virtual int OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
+  virtual int Perform(uint32_t operation, ...);
+  virtual void SetSecureDisplay(bool secure_display_active);
+  virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height);
+  virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+  virtual void GetPanelResolution(uint32_t *width, uint32_t *height);
+  virtual std::string Dump(void);
+
+  // Captures frame output in the buffer specified by output_buffer_info. The API is
+  // non-blocking and the client is expected to check operation status later on.
+  // Returns -1 if the input is invalid.
+  virtual int FrameCaptureAsync(const BufferInfo &output_buffer_info, bool post_processed) {
+    return -1;
+  }
+  // Returns the status of frame capture operation requested with FrameCaptureAsync().
+  // -EAGAIN : No status obtain yet, call API again after another frame.
+  // < 0 : Operation happened but failed.
+  // 0 : Success.
+  virtual int GetFrameCaptureStatus() { return -EAGAIN; }
+
+  virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data) {
+    return kErrorNotSupported;
+  }
+
+  // Display Configurations
+  virtual int SetActiveDisplayConfig(int config);
+  virtual int GetActiveDisplayConfig(uint32_t *config);
+  virtual int GetDisplayConfigCount(uint32_t *count);
+  virtual int GetDisplayAttributesForConfig(int config,
+                                            DisplayConfigVariableInfo *display_attributes);
+  template <typename... Args>
+  int32_t CallLayerFunction(hwc2_layer_t layer, HWC2::Error (HWCLayer::*member)(Args... ),
+                            Args... args) {
+    auto status = HWC2::Error::BadLayer;
+    validated_ = false;
+    auto hwc_layer = GetHWCLayer(layer);
+    if (hwc_layer != nullptr) {
+      status = (hwc_layer->*member)(std::forward<Args>(args)...);
+    }
+
+    return INT32(status);
+  }
+
+  int SetPanelBrightness(int level);
+  int GetPanelBrightness(int *level);
+  int ToggleScreenUpdates(bool enable);
+  int ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload, PPDisplayAPIPayload *out_payload,
+                           PPPendingParams *pending_action);
+  void SolidFillPrepare();
+  void SolidFillCommit();
+  DisplayClass GetDisplayClass();
+  int GetVisibleDisplayRect(hwc_rect_t *rect);
+  void BuildLayerStack(void);
+  void BuildSolidFillStack(void);
+  HWCLayer *GetHWCLayer(hwc2_layer_t layer);
+
+  // HWC2 APIs
+  virtual HWC2::Error AcceptDisplayChanges(void);
+  virtual HWC2::Error GetActiveConfig(hwc2_config_t *out_config);
+  virtual HWC2::Error SetActiveConfig(hwc2_config_t config);
+  virtual HWC2::Error SetClientTarget(buffer_handle_t target, int32_t acquire_fence,
+                                      int32_t dataspace, hwc_region_t damage);
+  virtual HWC2::Error SetColorMode(android_color_mode_t mode) {
+    return HWC2::Error::Unsupported;
+  }
+  virtual HWC2::Error SetColorModeById(int32_t color_mode_id) {
+    return HWC2::Error::Unsupported;
+  }
+  virtual HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint) {
+    return HWC2::Error::Unsupported;
+  }
+  virtual HWC2::Error HandleColorModeTransform(android_color_mode_t mode,
+                                               android_color_transform_t hint,
+                                               const double *matrix) {
+    return HWC2::Error::Unsupported;
+  }
+  virtual HWC2::Error GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs);
+  virtual HWC2::Error GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
+                                          int32_t *out_value);
+  virtual HWC2::Error GetClientTargetSupport(uint32_t width, uint32_t height, int32_t format,
+                                             int32_t dataspace);
+  virtual HWC2::Error GetColorModes(uint32_t *outNumModes, android_color_mode_t *outModes);
+  virtual HWC2::Error GetChangedCompositionTypes(uint32_t *out_num_elements,
+                                                 hwc2_layer_t *out_layers, int32_t *out_types);
+  virtual HWC2::Error GetDisplayRequests(int32_t *out_display_requests, uint32_t *out_num_elements,
+                                         hwc2_layer_t *out_layers, int32_t *out_layer_requests);
+  virtual HWC2::Error GetDisplayName(uint32_t *out_size, char *out_name);
+  virtual HWC2::Error GetDisplayType(int32_t *out_type);
+  virtual HWC2::Error SetCursorPosition(hwc2_layer_t layer, int x, int y);
+  virtual HWC2::Error SetVsyncEnabled(HWC2::Vsync enabled);
+  virtual HWC2::Error SetPowerMode(HWC2::PowerMode mode);
+  virtual HWC2::Error CreateLayer(hwc2_layer_t *out_layer_id);
+  virtual HWC2::Error DestroyLayer(hwc2_layer_t layer_id);
+  virtual HWC2::Error SetLayerZOrder(hwc2_layer_t layer_id, uint32_t z);
+  virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests) = 0;
+  virtual HWC2::Error GetReleaseFences(uint32_t *out_num_elements, hwc2_layer_t *out_layers,
+                                       int32_t *out_fences);
+  virtual HWC2::Error Present(int32_t *out_retire_fence) = 0;
+  virtual HWC2::Error GetHdrCapabilities(uint32_t *out_num_types, int32_t* out_types,
+                                         float* out_max_luminance,
+                                         float* out_max_average_luminance,
+                                         float* out_min_luminance);
+
+ protected:
+  enum DisplayStatus {
+    kDisplayStatusOffline = 0,
+    kDisplayStatusOnline,
+    kDisplayStatusPause,
+    kDisplayStatusResume,
+  };
+
+  // Maximum number of layers supported by display manager.
+  static const uint32_t kMaxLayerCount = 32;
+
+  HWCDisplay(CoreInterface *core_intf, HWCCallbacks *callbacks, DisplayType type, hwc2_display_t id,
+             bool needs_blit, qService::QService *qservice, DisplayClass display_class,
+             BufferAllocator *buffer_allocator);
+
+  // DisplayEventHandler methods
+  virtual DisplayError VSync(const DisplayEventVSync &vsync);
+  virtual DisplayError Refresh();
+  virtual DisplayError CECMessage(char *message);
+  virtual void DumpOutputBuffer(const BufferInfo &buffer_info, void *base, int fence);
+  virtual HWC2::Error PrepareLayerStack(uint32_t *out_num_types, uint32_t *out_num_requests);
+  virtual HWC2::Error CommitLayerStack(void);
+  virtual HWC2::Error PostCommitLayerStack(int32_t *out_retire_fence);
+  virtual DisplayError DisablePartialUpdateOneFrame() {
+    return kErrorNotSupported;
+  }
+  LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
+  const char *GetDisplayString();
+  void MarkLayersForGPUBypass(void);
+  void MarkLayersForClientComposition(void);
+  virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
+  bool SingleLayerUpdating(void);
+  bool IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions);
+  bool IsLayerUpdating(const Layer *layer);
+  uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
+  virtual void CloseAcquireFds();
+  virtual void ClearRequestFlags();
+
+  enum {
+    INPUT_LAYER_DUMP,
+    OUTPUT_LAYER_DUMP,
+  };
+
+  CoreInterface *core_intf_ = nullptr;
+  HWCCallbacks *callbacks_  = nullptr;
+  HWCBufferAllocator *buffer_allocator_ = NULL;
+  DisplayType type_;
+  hwc2_display_t id_;
+  bool needs_blit_ = false;
+  DisplayInterface *display_intf_ = NULL;
+  LayerStack layer_stack_;
+  HWCLayer *client_target_ = nullptr;                   // Also known as framebuffer target
+  std::map<hwc2_layer_t, HWCLayer *> layer_map_;        // Look up by Id - TODO
+  std::multiset<HWCLayer *, SortLayersByZ> layer_set_;  // Maintain a set sorted by Z
+  std::map<hwc2_layer_t, HWC2::Composition> layer_changes_;
+  std::map<hwc2_layer_t, HWC2::LayerRequest> layer_requests_;
+  bool flush_on_error_ = false;
+  bool flush_ = false;
+  uint32_t dump_frame_count_ = 0;
+  uint32_t dump_frame_index_ = 0;
+  bool dump_input_layers_ = false;
+  HWC2::PowerMode last_power_mode_;
+  bool swap_interval_zero_ = false;
+  bool display_paused_ = false;
+  uint32_t min_refresh_rate_ = 0;
+  uint32_t max_refresh_rate_ = 0;
+  uint32_t current_refresh_rate_ = 0;
+  bool use_metadata_refresh_rate_ = false;
+  uint32_t metadata_refresh_rate_ = 0;
+  uint32_t force_refresh_rate_ = 0;
+  bool boot_animation_completed_ = false;
+  bool shutdown_pending_ = false;
+  bool use_blit_comp_ = false;
+  bool secure_display_active_ = false;
+  bool skip_prepare_ = false;
+  bool solid_fill_enable_ = false;
+  Layer *solid_fill_layer_ = NULL;
+  LayerRect solid_fill_rect_ = {};
+  uint32_t solid_fill_color_ = 0;
+  LayerRect display_rect_;
+  bool validated_ = false;
+  bool color_tranform_failed_ = false;
+  HWCColorMode *color_mode_ = NULL;
+  HWCToneMapper *tone_mapper_ = nullptr;
+  int disable_hdr_handling_ = 0;  // disables HDR handling.
+
+ private:
+  void DumpInputBuffers(void);
+  qService::QService *qservice_ = NULL;
+  DisplayClass display_class_;
+  uint32_t geometry_changes_ = GeometryChanges::kNone;
+};
+
+inline int HWCDisplay::Perform(uint32_t operation, ...) {
+  return 0;
+}
+
+}  // namespace sdm
+
+#endif  // __HWC_DISPLAY_H__
diff --git a/sdm845/sdm/libs/hwc2/hwc_display_external.cpp b/sdm845/sdm/libs/hwc2/hwc_display_external.cpp
new file mode 100644
index 0000000..a8f8480
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_display_external.cpp
@@ -0,0 +1,218 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cutils/properties.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <algorithm>
+
+#include "hwc_display_external.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayExternal"
+
+namespace sdm {
+
+int HWCDisplayExternal::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+                               HWCCallbacks *callbacks, qService::QService *qservice,
+                               HWCDisplay **hwc_display) {
+  return Create(core_intf, buffer_allocator, callbacks, 0, 0, qservice, false, hwc_display);
+}
+
+int HWCDisplayExternal::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+                               HWCCallbacks *callbacks,
+                               uint32_t primary_width, uint32_t primary_height,
+                               qService::QService *qservice, bool use_primary_res,
+                               HWCDisplay **hwc_display) {
+  uint32_t external_width = 0;
+  uint32_t external_height = 0;
+  DisplayError error = kErrorNone;
+
+  HWCDisplay *hwc_display_external = new HWCDisplayExternal(core_intf, buffer_allocator, callbacks,
+                                                            qservice);
+  int status = hwc_display_external->Init();
+  if (status) {
+    delete hwc_display_external;
+    return status;
+  }
+
+  error = hwc_display_external->GetMixerResolution(&external_width, &external_height);
+  if (error != kErrorNone) {
+    return -EINVAL;
+  }
+
+  if (primary_width && primary_height) {
+    // use_primary_res means HWCDisplayExternal should directly set framebuffer resolution to the
+    // provided primary_width and primary_height
+    if (use_primary_res) {
+      external_width = primary_width;
+      external_height = primary_height;
+    } else {
+      int downscale_enabled = 0;
+      HWCDebugHandler::Get()->GetProperty("sdm.debug.downscale_external", &downscale_enabled);
+      if (downscale_enabled) {
+        GetDownscaleResolution(primary_width, primary_height, &external_width, &external_height);
+      }
+    }
+  }
+
+  status = hwc_display_external->SetFrameBufferResolution(external_width, external_height);
+  if (status) {
+    Destroy(hwc_display_external);
+    return status;
+  }
+
+  *hwc_display = hwc_display_external;
+
+  return status;
+}
+
+void HWCDisplayExternal::Destroy(HWCDisplay *hwc_display) {
+  hwc_display->Deinit();
+  delete hwc_display;
+}
+
+HWCDisplayExternal::HWCDisplayExternal(CoreInterface *core_intf,
+                                       HWCBufferAllocator *buffer_allocator,
+                                       HWCCallbacks *callbacks,
+                                       qService::QService *qservice)
+    : HWCDisplay(core_intf, callbacks, kHDMI, HWC_DISPLAY_EXTERNAL, false, qservice,
+                 DISPLAY_CLASS_EXTERNAL, buffer_allocator) {
+}
+
+HWC2::Error HWCDisplayExternal::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+  auto status = HWC2::Error::None;
+
+  if (secure_display_active_) {
+    MarkLayersForGPUBypass();
+    return status;
+  }
+
+  BuildLayerStack();
+
+  if (layer_set_.empty()) {
+    flush_ = true;
+    return status;
+  }
+
+  // TODO(user): SetRefreshRate need to follow new interface when added.
+
+  status = PrepareLayerStack(out_num_types, out_num_requests);
+  return status;
+}
+
+HWC2::Error HWCDisplayExternal::Present(int32_t *out_retire_fence) {
+  auto status = HWC2::Error::None;
+
+  if (!secure_display_active_) {
+    status = HWCDisplay::CommitLayerStack();
+    if (status == HWC2::Error::None) {
+      status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
+    }
+  }
+  CloseAcquireFds();
+  return status;
+}
+
+void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+  if (display_intf_->IsUnderscanSupported()) {
+    return;
+  }
+
+  // Read user defined width and height ratio
+  int width = 0, height = 0;
+  HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_width", &width);
+  float width_ratio = FLOAT(width) / 100.0f;
+  HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_height", &height);
+  float height_ratio = FLOAT(height) / 100.0f;
+
+  if (width_ratio == 0.0f || height_ratio == 0.0f) {
+    return;
+  }
+
+  uint32_t mixer_width = 0;
+  uint32_t mixer_height = 0;
+  GetMixerResolution(&mixer_width, &mixer_height);
+
+  if (mixer_width == 0 || mixer_height == 0) {
+    DLOGV("Invalid mixer dimensions (%d, %d)", mixer_width, mixer_height);
+    return;
+  }
+
+  uint32_t new_mixer_width = UINT32(mixer_width * FLOAT(1.0f - width_ratio));
+  uint32_t new_mixer_height = UINT32(mixer_height * FLOAT(1.0f - height_ratio));
+
+  int x_offset = INT((FLOAT(mixer_width) * width_ratio) / 2.0f);
+  int y_offset = INT((FLOAT(mixer_height) * height_ratio) / 2.0f);
+
+  display_frame->left = (display_frame->left * INT32(new_mixer_width) / INT32(mixer_width))
+                        + x_offset;
+  display_frame->top = (display_frame->top * INT32(new_mixer_height) / INT32(mixer_height)) +
+                       y_offset;
+  display_frame->right = ((display_frame->right * INT32(new_mixer_width)) / INT32(mixer_width)) +
+                         x_offset;
+  display_frame->bottom = ((display_frame->bottom * INT32(new_mixer_height)) / INT32(mixer_height))
+                          + y_offset;
+}
+
+void HWCDisplayExternal::SetSecureDisplay(bool secure_display_active) {
+  if (secure_display_active_ != secure_display_active) {
+    secure_display_active_ = secure_display_active;
+
+    if (secure_display_active_) {
+      DisplayError error = display_intf_->Flush();
+      if (error != kErrorNone) {
+        DLOGE("Flush failed. Error = %d", error);
+      }
+    }
+  }
+  return;
+}
+
+static void 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;
+}
+
+void HWCDisplayExternal::GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
+                                                uint32_t *non_primary_width,
+                                                uint32_t *non_primary_height) {
+  uint32_t primary_area = primary_width * primary_height;
+  uint32_t non_primary_area = (*non_primary_width) * (*non_primary_height);
+
+  if (primary_area > non_primary_area) {
+    if (primary_height > primary_width) {
+      std::swap(primary_height, primary_width);
+    }
+    AdjustSourceResolution(primary_width, primary_height, non_primary_width, non_primary_height);
+  }
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc2/hwc_display_external.h b/sdm845/sdm/libs/hwc2/hwc_display_external.h
new file mode 100644
index 0000000..802a77c
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_display_external.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HWC_DISPLAY_EXTERNAL_H__
+#define __HWC_DISPLAY_EXTERNAL_H__
+
+#include "hwc_display.h"
+
+namespace sdm {
+
+class HWCDisplayExternal : public HWCDisplay {
+ public:
+  static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+                    HWCCallbacks *callbacks, uint32_t primary_width,
+                    uint32_t primary_height, qService::QService *qservice, bool use_primary_res,
+                    HWCDisplay **hwc_display);
+  static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+                    HWCCallbacks *callbacks, qService::QService *qservice,
+                    HWCDisplay **hwc_display);
+  static void Destroy(HWCDisplay *hwc_display);
+  virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
+  virtual HWC2::Error Present(int32_t *out_retire_fence);
+  virtual void SetSecureDisplay(bool secure_display_active);
+
+ private:
+  HWCDisplayExternal(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+                     HWCCallbacks *callbacks, qService::QService *qservice);
+  void ApplyScanAdjustment(hwc_rect_t *display_frame);
+  static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
+                                     uint32_t *virtual_width, uint32_t *virtual_height);
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_DISPLAY_EXTERNAL_H__
diff --git a/sdm845/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm845/sdm/libs/hwc2/hwc_display_primary.cpp
new file mode 100644
index 0000000..2fcf2a9
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -0,0 +1,583 @@
+/*
+* Copyright (c) 2014 - 2017, 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 <sync/sync.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "hwc_display_primary.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayPrimary"
+
+namespace sdm {
+
+int HWCDisplayPrimary::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+                              HWCCallbacks *callbacks, qService::QService *qservice,
+                              HWCDisplay **hwc_display) {
+  int status = 0;
+  uint32_t primary_width = 0;
+  uint32_t primary_height = 0;
+
+  HWCDisplay *hwc_display_primary =
+      new HWCDisplayPrimary(core_intf, buffer_allocator, callbacks, qservice);
+  status = hwc_display_primary->Init();
+  if (status) {
+    delete hwc_display_primary;
+    return status;
+  }
+
+  hwc_display_primary->GetMixerResolution(&primary_width, &primary_height);
+  int width = 0, height = 0;
+  HWCDebugHandler::Get()->GetProperty("sdm.fb_size_width", &width);
+  HWCDebugHandler::Get()->GetProperty("sdm.fb_size_height", &height);
+  if (width > 0 && height > 0) {
+    primary_width = UINT32(width);
+    primary_height = UINT32(height);
+  }
+
+  status = hwc_display_primary->SetFrameBufferResolution(primary_width, primary_height);
+  if (status) {
+    Destroy(hwc_display_primary);
+    return status;
+  }
+
+  *hwc_display = hwc_display_primary;
+
+  return status;
+}
+
+void HWCDisplayPrimary::Destroy(HWCDisplay *hwc_display) {
+  hwc_display->Deinit();
+  delete hwc_display;
+}
+
+HWCDisplayPrimary::HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+                                     HWCCallbacks *callbacks, qService::QService *qservice)
+    : HWCDisplay(core_intf, callbacks, kPrimary, HWC_DISPLAY_PRIMARY, true, qservice,
+                 DISPLAY_CLASS_PRIMARY, buffer_allocator),
+      buffer_allocator_(buffer_allocator),
+      cpu_hint_(NULL) {
+}
+
+int HWCDisplayPrimary::Init() {
+  cpu_hint_ = new CPUHint();
+  if (cpu_hint_->Init(static_cast<HWCDebugHandler *>(HWCDebugHandler::Get())) != kErrorNone) {
+    delete cpu_hint_;
+    cpu_hint_ = NULL;
+  }
+
+  use_metadata_refresh_rate_ = true;
+  int disable_metadata_dynfps = 0;
+  HWCDebugHandler::Get()->GetProperty("persist.metadata_dynfps.disable", &disable_metadata_dynfps);
+  if (disable_metadata_dynfps) {
+    use_metadata_refresh_rate_ = false;
+  }
+
+  int status = HWCDisplay::Init();
+  if (status) {
+    return status;
+  }
+  color_mode_ = new HWCColorMode(display_intf_);
+  color_mode_->Init();
+
+  return status;
+}
+
+void HWCDisplayPrimary::ProcessBootAnimCompleted() {
+  uint32_t numBootUpLayers = 0;
+  // TODO(user): Remove this hack
+
+  numBootUpLayers = static_cast<uint32_t>(Debug::GetBootAnimLayerCount());
+
+  if (numBootUpLayers == 0) {
+    numBootUpLayers = 2;
+  }
+  /* All other checks namely "init.svc.bootanim" or
+  * HWC_GEOMETRY_CHANGED fail in correctly identifying the
+  * exact bootup transition to homescreen
+  */
+  char property[PROPERTY_VALUE_MAX];
+  bool isEncrypted = false;
+  bool main_class_services_started = false;
+  property_get("ro.crypto.state", property, "unencrypted");
+  if (!strcmp(property, "encrypted")) {
+    property_get("ro.crypto.type", property, "block");
+    if (!strcmp(property, "block")) {
+      isEncrypted = true;
+      property_get("vold.decrypt", property, "");
+      if (!strcmp(property, "trigger_restart_framework")) {
+        main_class_services_started = true;
+      }
+    }
+  }
+
+  if ((!isEncrypted || (isEncrypted && main_class_services_started)) &&
+      (layer_set_.size() > numBootUpLayers)) {
+    DLOGI("Applying default mode");
+    boot_animation_completed_ = true;
+    // Applying default mode after bootanimation is finished And
+    // If Data is Encrypted, it is ready for access.
+    if (display_intf_)
+      display_intf_->ApplyDefaultDisplayMode();
+  }
+}
+
+HWC2::Error HWCDisplayPrimary::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+  auto status = HWC2::Error::None;
+  DisplayError error = kErrorNone;
+
+  if (display_paused_) {
+    MarkLayersForGPUBypass();
+    return status;
+  }
+
+  if (color_tranform_failed_) {
+    // Must fall back to client composition
+    MarkLayersForClientComposition();
+  }
+
+  // Fill in the remaining blanks in the layers and add them to the SDM layerstack
+  BuildLayerStack();
+  // Checks and replaces layer stack for solid fill
+  SolidFillPrepare();
+
+  bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
+
+  if (frame_capture_buffer_queued_ || pending_output_dump) {
+    // RHS values were set in FrameCaptureAsync() called from a binder thread. They are picked up
+    // here in a subsequent draw round.
+    layer_stack_.output_buffer = &output_buffer_;
+    layer_stack_.flags.post_processed_output = post_processed_output_;
+  }
+
+  bool one_updating_layer = SingleLayerUpdating();
+  ToggleCPUHint(one_updating_layer);
+
+  uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
+  bool final_rate = force_refresh_rate_ ? true : false;
+  error = display_intf_->SetRefreshRate(refresh_rate, final_rate);
+  if (error == kErrorNone) {
+    // On success, set current refresh rate to new refresh rate
+    current_refresh_rate_ = refresh_rate;
+  }
+
+  if (layer_set_.empty()) {
+    flush_ = true;
+    return status;
+  }
+
+  status = PrepareLayerStack(out_num_types, out_num_requests);
+  return status;
+}
+
+HWC2::Error HWCDisplayPrimary::Present(int32_t *out_retire_fence) {
+  auto status = HWC2::Error::None;
+  if (display_paused_) {
+    // TODO(user): From old HWC implementation
+    // If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd
+    // Revisit this when validating display_paused
+    DisplayError error = display_intf_->Flush();
+    if (error != kErrorNone) {
+      DLOGE("Flush failed. Error = %d", error);
+    }
+  } else {
+    status = HWCDisplay::CommitLayerStack();
+    if (status == HWC2::Error::None) {
+      HandleFrameOutput();
+      SolidFillCommit();
+      status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
+    }
+  }
+
+  CloseAcquireFds();
+  return status;
+}
+
+HWC2::Error HWCDisplayPrimary::GetColorModes(uint32_t *out_num_modes,
+                                             android_color_mode_t *out_modes) {
+  if (out_modes == nullptr) {
+    *out_num_modes = color_mode_->GetColorModeCount();
+  } else {
+    color_mode_->GetColorModes(out_num_modes, out_modes);
+  }
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplayPrimary::SetColorMode(android_color_mode_t mode) {
+  auto status = color_mode_->SetColorMode(mode);
+  if (status != HWC2::Error::None) {
+    DLOGE("failed for mode = %d", mode);
+    return status;
+  }
+
+  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+
+  return status;
+}
+
+HWC2::Error HWCDisplayPrimary::SetColorModeById(int32_t color_mode_id) {
+  auto status = color_mode_->SetColorModeById(color_mode_id);
+  if (status != HWC2::Error::None) {
+    DLOGE("failed for mode = %d", color_mode_id);
+    return status;
+  }
+
+  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+
+  return status;
+}
+
+HWC2::Error HWCDisplayPrimary::SetColorTransform(const float *matrix,
+                                                 android_color_transform_t hint) {
+  if (!matrix) {
+    return HWC2::Error::BadParameter;
+  }
+
+  auto status = color_mode_->SetColorTransform(matrix, hint);
+  if (status != HWC2::Error::None) {
+    DLOGE("failed for hint = %d", hint);
+    color_tranform_failed_ = true;
+    return status;
+  }
+
+  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+  color_tranform_failed_ = false;
+
+  return status;
+}
+
+int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
+  va_list args;
+  va_start(args, operation);
+  int val = 0;
+  LayerRect *rect = NULL;
+
+  switch (operation) {
+    case SET_METADATA_DYN_REFRESH_RATE:
+      val = va_arg(args, int32_t);
+      SetMetaDataRefreshRateFlag(val);
+      break;
+    case SET_BINDER_DYN_REFRESH_RATE:
+      val = va_arg(args, int32_t);
+      ForceRefreshRate(UINT32(val));
+      break;
+    case SET_DISPLAY_MODE:
+      val = va_arg(args, int32_t);
+      SetDisplayMode(UINT32(val));
+      break;
+    case SET_QDCM_SOLID_FILL_INFO:
+      val = va_arg(args, int32_t);
+      SetQDCMSolidFillInfo(true, UINT32(val));
+      break;
+    case UNSET_QDCM_SOLID_FILL_INFO:
+      val = va_arg(args, int32_t);
+      SetQDCMSolidFillInfo(false, UINT32(val));
+      break;
+    case SET_QDCM_SOLID_FILL_RECT:
+      rect = va_arg(args, LayerRect*);
+      solid_fill_rect_ = *rect;
+      break;
+    default:
+      DLOGW("Invalid operation %d", operation);
+      va_end(args);
+      return -EINVAL;
+  }
+  va_end(args);
+
+  return 0;
+}
+
+DisplayError HWCDisplayPrimary::SetDisplayMode(uint32_t mode) {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->SetDisplayMode(mode);
+  }
+
+  return error;
+}
+
+void HWCDisplayPrimary::SetMetaDataRefreshRateFlag(bool enable) {
+  int disable_metadata_dynfps = 0;
+
+  HWCDebugHandler::Get()->GetProperty("persist.metadata_dynfps.disable", &disable_metadata_dynfps);
+  if (disable_metadata_dynfps) {
+    return;
+  }
+  use_metadata_refresh_rate_ = enable;
+}
+
+void HWCDisplayPrimary::SetQDCMSolidFillInfo(bool enable, uint32_t color) {
+  solid_fill_enable_ = enable;
+  solid_fill_color_ = color;
+}
+
+void HWCDisplayPrimary::ToggleCPUHint(bool set) {
+  if (!cpu_hint_) {
+    return;
+  }
+
+  if (set) {
+    cpu_hint_->Set();
+  } else {
+    cpu_hint_->Reset();
+  }
+}
+
+void HWCDisplayPrimary::SetSecureDisplay(bool secure_display_active) {
+  if (secure_display_active_ != secure_display_active) {
+    // Skip Prepare and call Flush for null commit
+    DLOGI("SecureDisplay state changed from %d to %d Needs Flush!!", secure_display_active_,
+          secure_display_active);
+    secure_display_active_ = secure_display_active;
+    skip_prepare_ = true;
+  }
+  return;
+}
+
+void HWCDisplayPrimary::ForceRefreshRate(uint32_t refresh_rate) {
+  if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
+      force_refresh_rate_ == refresh_rate) {
+    // Cannot honor force refresh rate, as its beyond the range or new request is same
+    return;
+  }
+
+  force_refresh_rate_ = refresh_rate;
+
+  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+
+  return;
+}
+
+uint32_t HWCDisplayPrimary::GetOptimalRefreshRate(bool one_updating_layer) {
+  if (force_refresh_rate_) {
+    return force_refresh_rate_;
+  } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
+    return metadata_refresh_rate_;
+  }
+
+  return max_refresh_rate_;
+}
+
+DisplayError HWCDisplayPrimary::Refresh() {
+  DisplayError error = kErrorNone;
+
+  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+
+  return error;
+}
+
+void HWCDisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+  display_intf_->SetIdleTimeoutMs(timeout_ms);
+}
+
+static void SetLayerBuffer(const BufferInfo &output_buffer_info, LayerBuffer *output_buffer) {
+  const BufferConfig& buffer_config = output_buffer_info.buffer_config;
+  const AllocatedBufferInfo &alloc_buffer_info = output_buffer_info.alloc_buffer_info;
+
+  output_buffer->width = alloc_buffer_info.aligned_width;
+  output_buffer->height = alloc_buffer_info.aligned_height;
+  output_buffer->unaligned_width = buffer_config.width;
+  output_buffer->unaligned_height = buffer_config.height;
+  output_buffer->format = buffer_config.format;
+  output_buffer->planes[0].fd = alloc_buffer_info.fd;
+  output_buffer->planes[0].stride = alloc_buffer_info.stride;
+}
+
+void HWCDisplayPrimary::HandleFrameOutput() {
+  if (frame_capture_buffer_queued_) {
+    HandleFrameCapture();
+  } else if (dump_output_to_file_) {
+    HandleFrameDump();
+  }
+}
+
+void HWCDisplayPrimary::HandleFrameCapture() {
+  if (output_buffer_.release_fence_fd >= 0) {
+    frame_capture_status_ = sync_wait(output_buffer_.release_fence_fd, 1000);
+    ::close(output_buffer_.release_fence_fd);
+    output_buffer_.release_fence_fd = -1;
+  }
+
+  frame_capture_buffer_queued_ = false;
+  post_processed_output_ = false;
+  output_buffer_ = {};
+}
+
+void HWCDisplayPrimary::HandleFrameDump() {
+  if (dump_frame_count_ && output_buffer_.release_fence_fd >= 0) {
+    int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
+    ::close(output_buffer_.release_fence_fd);
+    output_buffer_.release_fence_fd = -1;
+    if (ret < 0) {
+      DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+    } else {
+      DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence_fd);
+    }
+  }
+
+  if (0 == dump_frame_count_) {
+    dump_output_to_file_ = false;
+    // Unmap and Free buffer
+    if (munmap(output_buffer_base_, output_buffer_info_.alloc_buffer_info.size) != 0) {
+      DLOGE("unmap failed with err %d", errno);
+    }
+    if (buffer_allocator_->FreeBuffer(&output_buffer_info_) != 0) {
+      DLOGE("FreeBuffer failed");
+    }
+
+    post_processed_output_ = false;
+    output_buffer_ = {};
+    output_buffer_info_ = {};
+    output_buffer_base_ = nullptr;
+  }
+}
+
+void HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+  HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
+  dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
+  DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
+
+  if (!count || !dump_output_to_file_) {
+    return;
+  }
+
+  // Allocate and map output buffer
+  output_buffer_info_ = {};
+  // Since we dump DSPP output use Panel resolution.
+  GetPanelResolution(&output_buffer_info_.buffer_config.width,
+                     &output_buffer_info_.buffer_config.height);
+  output_buffer_info_.buffer_config.format = kFormatRGB888;
+  output_buffer_info_.buffer_config.buffer_count = 1;
+  if (buffer_allocator_->AllocateBuffer(&output_buffer_info_) != 0) {
+    DLOGE("Buffer allocation failed");
+    output_buffer_info_ = {};
+    return;
+  }
+
+  void *buffer = mmap(NULL, output_buffer_info_.alloc_buffer_info.size, PROT_READ | PROT_WRITE,
+                      MAP_SHARED, output_buffer_info_.alloc_buffer_info.fd, 0);
+
+  if (buffer == MAP_FAILED) {
+    DLOGE("mmap failed with err %d", errno);
+    buffer_allocator_->FreeBuffer(&output_buffer_info_);
+    output_buffer_info_ = {};
+    return;
+  }
+
+  output_buffer_base_ = buffer;
+  post_processed_output_ = true;
+  DisablePartialUpdateOneFrame();
+}
+
+int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo &output_buffer_info,
+                                         bool post_processed_output) {
+  // Note: This function is called in context of a binder thread and a lock is already held
+  if (output_buffer_info.alloc_buffer_info.fd < 0) {
+    DLOGE("Invalid fd %d", output_buffer_info.alloc_buffer_info.fd);
+    return -1;
+  }
+
+  auto panel_width = 0u;
+  auto panel_height = 0u;
+  auto fb_width = 0u;
+  auto fb_height = 0u;
+
+  GetPanelResolution(&panel_width, &panel_height);
+  GetFrameBufferResolution(&fb_width, &fb_height);
+
+  if (post_processed_output && (output_buffer_info_.buffer_config.width < panel_width ||
+                                output_buffer_info_.buffer_config.height < panel_height)) {
+    DLOGE("Buffer dimensions should not be less than panel resolution");
+    return -1;
+  } else if (!post_processed_output && (output_buffer_info_.buffer_config.width < fb_width ||
+                                        output_buffer_info_.buffer_config.height < fb_height)) {
+    DLOGE("Buffer dimensions should not be less than FB resolution");
+    return -1;
+  }
+
+  SetLayerBuffer(output_buffer_info, &output_buffer_);
+  post_processed_output_ = post_processed_output;
+  frame_capture_buffer_queued_ = true;
+  // Status is only cleared on a new call to dump and remains valid otherwise
+  frame_capture_status_ = -EAGAIN;
+  DisablePartialUpdateOneFrame();
+
+  return 0;
+}
+
+DisplayError HWCDisplayPrimary::SetDetailEnhancerConfig
+                                   (const DisplayDetailEnhancerData &de_data) {
+  DisplayError error = kErrorNotSupported;
+
+  if (display_intf_) {
+    error = display_intf_->SetDetailEnhancerData(de_data);
+  }
+  return error;
+}
+
+DisplayError HWCDisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->ControlPartialUpdate(enable, pending);
+  }
+
+  return error;
+}
+
+DisplayError HWCDisplayPrimary::DisablePartialUpdateOneFrame() {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->DisablePartialUpdateOneFrame();
+  }
+
+  return error;
+}
+
+
+DisplayError HWCDisplayPrimary::SetMixerResolution(uint32_t width, uint32_t height) {
+  return display_intf_->SetMixerResolution(width, height);
+}
+
+DisplayError HWCDisplayPrimary::GetMixerResolution(uint32_t *width, uint32_t *height) {
+  return display_intf_->GetMixerResolution(width, height);
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc2/hwc_display_primary.h b/sdm845/sdm/libs/hwc2/hwc_display_primary.h
new file mode 100644
index 0000000..4df65b3
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_display_primary.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HWC_DISPLAY_PRIMARY_H__
+#define __HWC_DISPLAY_PRIMARY_H__
+
+#include <string>
+
+#include "cpuhint.h"
+#include "hwc_display.h"
+
+namespace sdm {
+
+class HWCDisplayPrimary : public HWCDisplay {
+ public:
+  enum {
+    SET_METADATA_DYN_REFRESH_RATE,
+    SET_BINDER_DYN_REFRESH_RATE,
+    SET_DISPLAY_MODE,
+    SET_QDCM_SOLID_FILL_INFO,
+    UNSET_QDCM_SOLID_FILL_INFO,
+    SET_QDCM_SOLID_FILL_RECT,
+  };
+
+  static int Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+                    HWCCallbacks *callbacks, qService::QService *qservice,
+                    HWCDisplay **hwc_display);
+  static void Destroy(HWCDisplay *hwc_display);
+  virtual int Init();
+  virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
+  virtual HWC2::Error Present(int32_t *out_retire_fence);
+  virtual HWC2::Error GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes);
+  virtual HWC2::Error SetColorMode(android_color_mode_t mode);
+  virtual HWC2::Error SetColorModeById(int32_t color_mode_id);
+  virtual HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint);
+  virtual int Perform(uint32_t operation, ...);
+  virtual void SetSecureDisplay(bool secure_display_active);
+  virtual DisplayError Refresh();
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+  virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+  virtual int FrameCaptureAsync(const BufferInfo &output_buffer_info, bool post_processed);
+  virtual int GetFrameCaptureStatus() { return frame_capture_status_; }
+  virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data);
+  virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
+
+ private:
+  HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
+                    HWCCallbacks *callbacks, qService::QService *qservice);
+  void SetMetaDataRefreshRateFlag(bool enable);
+  virtual DisplayError SetDisplayMode(uint32_t mode);
+  virtual DisplayError DisablePartialUpdateOneFrame();
+  void ProcessBootAnimCompleted(void);
+  void SetQDCMSolidFillInfo(bool enable, uint32_t color);
+  void ToggleCPUHint(bool set);
+  void ForceRefreshRate(uint32_t refresh_rate);
+  uint32_t GetOptimalRefreshRate(bool one_updating_layer);
+  void HandleFrameOutput();
+  void HandleFrameCapture();
+  void HandleFrameDump();
+  DisplayError SetMixerResolution(uint32_t width, uint32_t height);
+  DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+
+  BufferAllocator *buffer_allocator_ = nullptr;
+  CPUHint *cpu_hint_ = nullptr;
+
+  // Primary output buffer configuration
+  LayerBuffer output_buffer_ = {};
+  bool post_processed_output_ = false;
+
+  // Members for 1 frame capture in a client provided buffer
+  bool frame_capture_buffer_queued_ = false;
+  int frame_capture_status_ = -EAGAIN;
+
+  // Members for N frame output dump to file
+  bool dump_output_to_file_ = false;
+  BufferInfo output_buffer_info_ = {};
+  void *output_buffer_base_ = nullptr;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_DISPLAY_PRIMARY_H__
diff --git a/sdm845/sdm/libs/hwc2/hwc_display_virtual.cpp b/sdm845/sdm/libs/hwc2/hwc_display_virtual.cpp
new file mode 100644
index 0000000..f77e9c9
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -0,0 +1,236 @@
+/*
+* Copyright (c) 2014-2017, 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 <sync/sync.h>
+#include <stdarg.h>
+#ifndef USE_GRALLOC1
+#include <gr.h>
+#endif
+
+#include "hwc_display_virtual.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayVirtual"
+
+namespace sdm {
+
+int HWCDisplayVirtual::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+                              HWCCallbacks *callbacks, uint32_t width,
+                              uint32_t height, int32_t *format, HWCDisplay **hwc_display) {
+  int status = 0;
+  HWCDisplayVirtual *hwc_display_virtual = new HWCDisplayVirtual(core_intf, buffer_allocator,
+                                                                 callbacks);
+
+  // TODO(user): Populate format correctly
+  DLOGI("Creating virtual display: w: %d h:%d format:0x%x", width, height, *format);
+
+  status = hwc_display_virtual->Init();
+  if (status) {
+    DLOGW("Failed to initialize virtual display");
+    delete hwc_display_virtual;
+    return status;
+  }
+
+  status = INT32(hwc_display_virtual->SetPowerMode(HWC2::PowerMode::On));
+  if (status) {
+    DLOGW("Failed to set power mode on virtual display");
+    Destroy(hwc_display_virtual);
+    return status;
+  }
+
+  status = hwc_display_virtual->SetConfig(width, height);
+  if (status) {
+    Destroy(hwc_display_virtual);
+    return status;
+  }
+
+  // TODO(user): Validate that we support this width/height
+  status = hwc_display_virtual->SetFrameBufferResolution(width, height);
+
+  if (status) {
+    DLOGW("Failed to set virtual display FB resolution");
+    Destroy(hwc_display_virtual);
+    return status;
+  }
+
+  *hwc_display = static_cast<HWCDisplay *>(hwc_display_virtual);
+
+  return 0;
+}
+
+void HWCDisplayVirtual::Destroy(HWCDisplay *hwc_display) {
+  hwc_display->Deinit();
+  delete hwc_display;
+}
+
+HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+                                     HWCCallbacks *callbacks)
+    : HWCDisplay(core_intf, callbacks, kVirtual, HWC_DISPLAY_VIRTUAL, false, NULL,
+                 DISPLAY_CLASS_VIRTUAL, buffer_allocator) {
+}
+
+int HWCDisplayVirtual::Init() {
+  output_buffer_ = new LayerBuffer();
+  return HWCDisplay::Init();
+}
+
+int HWCDisplayVirtual::Deinit() {
+  int status = 0;
+  if (output_buffer_) {
+    delete output_buffer_;
+    output_buffer_ = nullptr;
+  }
+  status = HWCDisplay::Deinit();
+
+  return status;
+}
+
+HWC2::Error HWCDisplayVirtual::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+  auto status = HWC2::Error::None;
+
+  if (display_paused_) {
+    MarkLayersForGPUBypass();
+    return status;
+  }
+
+  BuildLayerStack();
+  layer_stack_.output_buffer = output_buffer_;
+  status = PrepareLayerStack(out_num_types, out_num_requests);
+  return status;
+}
+
+HWC2::Error HWCDisplayVirtual::Present(int32_t *out_retire_fence) {
+  auto status = HWC2::Error::None;
+  if (display_paused_) {
+    DisplayError error = display_intf_->Flush();
+    if (error != kErrorNone) {
+      DLOGE("Flush failed. Error = %d", error);
+    }
+  } else {
+    status = HWCDisplay::CommitLayerStack();
+    if (status == HWC2::Error::None) {
+      if (dump_frame_count_ && !flush_ && dump_output_layer_) {
+        if (output_handle_ && output_handle_->base) {
+          BufferInfo buffer_info;
+          const private_handle_t *output_handle =
+              reinterpret_cast<const private_handle_t *>(output_buffer_->buffer_id);
+          buffer_info.buffer_config.width = static_cast<uint32_t>(output_handle->width);
+          buffer_info.buffer_config.height = static_cast<uint32_t>(output_handle->height);
+          buffer_info.buffer_config.format =
+              GetSDMFormat(output_handle->format, output_handle->flags);
+          buffer_info.alloc_buffer_info.size = static_cast<uint32_t>(output_handle->size);
+          DumpOutputBuffer(buffer_info, reinterpret_cast<void *>(output_handle->base),
+                           layer_stack_.retire_fence_fd);
+        }
+      }
+
+      status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
+    }
+  }
+  CloseAcquireFds();
+  close(output_buffer_->acquire_fence_fd);
+  return status;
+}
+
+int HWCDisplayVirtual::SetConfig(uint32_t width, uint32_t height) {
+  DisplayConfigVariableInfo variable_info;
+  variable_info.x_pixels = width;
+  variable_info.y_pixels = height;
+  // TODO(user): Need to get the framerate of primary display and update it.
+  variable_info.fps = 60;
+  return display_intf_->SetActiveConfig(&variable_info);
+}
+
+HWC2::Error HWCDisplayVirtual::SetOutputBuffer(buffer_handle_t buf, int32_t release_fence) {
+  if (buf == nullptr || release_fence == 0) {
+    return HWC2::Error::BadParameter;
+  }
+  const private_handle_t *output_handle = static_cast<const private_handle_t *>(buf);
+
+  // Fill output buffer parameters (width, height, format, plane information, fence)
+  output_buffer_->acquire_fence_fd = dup(release_fence);
+
+  if (output_handle) {
+    output_handle_ = output_handle;
+    output_buffer_->buffer_id = reinterpret_cast<uint64_t>(output_handle);
+    int output_handle_format = output_handle->format;
+
+    if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
+      output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
+    }
+
+    output_buffer_->format = GetSDMFormat(output_handle_format, output_handle->flags);
+
+    if (output_buffer_->format == kFormatInvalid) {
+      return HWC2::Error::BadParameter;
+    }
+
+    int aligned_width, aligned_height;
+#ifdef USE_GRALLOC1
+    buffer_allocator_->GetCustomWidthAndHeight(output_handle, &aligned_width, &aligned_height);
+#else
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, aligned_width,
+                                                          aligned_height);
+#endif
+
+    output_buffer_->width = UINT32(aligned_width);
+    output_buffer_->height = UINT32(aligned_height);
+    output_buffer_->unaligned_width = UINT32(output_handle->unaligned_width);
+    output_buffer_->unaligned_height = UINT32(output_handle->unaligned_height);
+    output_buffer_->flags.secure = 0;
+    output_buffer_->flags.video = 0;
+
+    if (sdm::SetCSC(output_handle, &output_buffer_->color_metadata) != kErrorNone) {
+      return HWC2::Error::BadParameter;
+    }
+
+    // TZ Protected Buffer - L1
+    if (output_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+      output_buffer_->flags.secure = 1;
+    }
+
+    // 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 = UINT32(output_handle->width);
+  }
+
+  return HWC2::Error::None;
+}
+
+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_);
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc2/hwc_display_virtual.h b/sdm845/sdm/libs/hwc2/hwc_display_virtual.h
new file mode 100644
index 0000000..36e8509
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_display_virtual.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __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:
+  static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+                    HWCCallbacks *callbacks, uint32_t width,
+                    uint32_t height, int32_t *format, HWCDisplay **hwc_display);
+  static void Destroy(HWCDisplay *hwc_display);
+  virtual int Init();
+  virtual int Deinit();
+  virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
+  virtual HWC2::Error Present(int32_t *out_retire_fence);
+  virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+  HWC2::Error SetOutputBuffer(buffer_handle_t buf, int32_t release_fence);
+
+ private:
+  HWCDisplayVirtual(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+                    HWCCallbacks *callbacks);
+  int SetConfig(uint32_t width, uint32_t height);
+
+  bool dump_output_layer_ = false;
+  LayerBuffer *output_buffer_ = NULL;
+  const private_handle_t *output_handle_ = nullptr;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_DISPLAY_VIRTUAL_H__
diff --git a/sdm845/sdm/libs/hwc2/hwc_layers.cpp b/sdm845/sdm/libs/hwc2/hwc_layers.cpp
new file mode 100644
index 0000000..7fcd56b
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_layers.cpp
@@ -0,0 +1,738 @@
+/*
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <qdMetaData.h>
+
+#include "hwc_layers.h"
+#ifndef USE_GRALLOC1
+#include <gr.h>
+#endif
+#include <utils/debug.h>
+#include <cmath>
+
+#define __CLASS__ "HWCLayer"
+
+namespace sdm {
+
+std::atomic<hwc2_layer_t> HWCLayer::next_id_(1);
+
+DisplayError SetCSC(const private_handle_t *pvt_handle, ColorMetaData *color_metadata) {
+  if (getMetaData(const_cast<private_handle_t *>(pvt_handle), GET_COLOR_METADATA,
+                  color_metadata) != 0) {
+    ColorSpace_t csc = ITU_R_601;
+    if (getMetaData(const_cast<private_handle_t *>(pvt_handle),  GET_COLOR_SPACE,
+                    &csc) == 0) {
+      if (csc == ITU_R_601_FR || csc == ITU_R_2020_FR) {
+        color_metadata->range = Range_Full;
+      }
+
+      switch (csc) {
+      case ITU_R_601:
+      case ITU_R_601_FR:
+        // video and display driver uses 601_525
+        color_metadata->colorPrimaries = ColorPrimaries_BT601_6_525;
+        break;
+      case ITU_R_709:
+        color_metadata->colorPrimaries = ColorPrimaries_BT709_5;
+        break;
+      case ITU_R_2020:
+      case ITU_R_2020_FR:
+        color_metadata->colorPrimaries = ColorPrimaries_BT2020;
+        break;
+      default:
+        DLOGE("Unsupported CSC: %d", csc);
+        return kErrorNotSupported;
+      }
+    } else {
+      return kErrorNotSupported;
+    }
+  }
+
+  return kErrorNone;
+}
+
+// Layer operations
+HWCLayer::HWCLayer(hwc2_display_t display_id, HWCBufferAllocator *buf_allocator)
+  : id_(next_id_++), display_id_(display_id), buffer_allocator_(buf_allocator) {
+  layer_ = new Layer();
+  // Fences are deferred, so the first time this layer is presented, return -1
+  // TODO(user): Verify that fences are properly obtained on suspend/resume
+  release_fences_.push(-1);
+}
+
+HWCLayer::~HWCLayer() {
+  // Close any fences left for this layer
+  while (!release_fences_.empty()) {
+    close(release_fences_.front());
+    release_fences_.pop();
+  }
+  close(ion_fd_);
+  if (layer_) {
+    delete layer_;
+  }
+}
+
+HWC2::Error HWCLayer::SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence) {
+  if (!buffer) {
+    DLOGE("Invalid buffer handle: %p on layer: %d", buffer, id_);
+    return HWC2::Error::BadParameter;
+  }
+
+  if (acquire_fence == 0) {
+    DLOGE("acquire_fence is zero");
+    return HWC2::Error::BadParameter;
+  }
+
+  const private_handle_t *handle = static_cast<const private_handle_t *>(buffer);
+
+  // Validate and dup ion fd from surfaceflinger
+  // This works around bug 30281222
+  if (handle->fd < 0) {
+    return HWC2::Error::BadParameter;
+  } else {
+    close(ion_fd_);
+    ion_fd_ = dup(handle->fd);
+  }
+
+  LayerBuffer *layer_buffer = &layer_->input_buffer;
+  int aligned_width, aligned_height;
+#ifdef USE_GRALLOC1
+  buffer_allocator_->GetCustomWidthAndHeight(handle, &aligned_width, &aligned_height);
+#else
+  AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(handle, aligned_width, aligned_height);
+#endif
+
+  layer_buffer->width = UINT32(aligned_width);
+  layer_buffer->height = UINT32(aligned_height);
+  layer_buffer->unaligned_width = UINT32(handle->unaligned_width);
+  layer_buffer->unaligned_height = UINT32(handle->unaligned_height);
+
+  layer_buffer->format = GetSDMFormat(handle->format, handle->flags);
+  if (SetMetaData(const_cast<private_handle_t *>(handle), layer_) != kErrorNone) {
+    return HWC2::Error::BadLayer;
+  }
+
+#ifdef USE_GRALLOC1
+  // TODO(user): Clean this up
+  if (handle->buffer_type == BUFFER_TYPE_VIDEO) {
+#else
+    if (handle->bufferType == BUFFER_TYPE_VIDEO) {
+#endif
+    layer_buffer->flags.video = true;
+  }
+  // TZ Protected Buffer - L1
+  if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+    layer_buffer->flags.secure = true;
+    if (handle->flags & private_handle_t::PRIV_FLAGS_CAMERA_WRITE) {
+      layer_buffer->flags.secure_camera = true;
+    }
+  }
+  if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
+    layer_buffer->flags.secure_display = true;
+  }
+
+  layer_buffer->planes[0].fd = ion_fd_;
+  layer_buffer->planes[0].offset = handle->offset;
+  layer_buffer->planes[0].stride = UINT32(handle->width);
+  layer_buffer->acquire_fence_fd = acquire_fence;
+  layer_buffer->size = handle->size;
+  layer_buffer->buffer_id = reinterpret_cast<uint64_t>(handle);
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerSurfaceDamage(hwc_region_t damage) {
+  layer_->dirty_regions.clear();
+  for (uint32_t i = 0; i < damage.numRects; i++) {
+    LayerRect rect;
+    SetRect(damage.rects[i], &rect);
+    layer_->dirty_regions.push_back(rect);
+  }
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerBlendMode(HWC2::BlendMode mode) {
+  LayerBlending blending = kBlendingPremultiplied;
+  switch (mode) {
+    case HWC2::BlendMode::Coverage:
+      blending = kBlendingCoverage;
+      break;
+    case HWC2::BlendMode::Premultiplied:
+      blending = kBlendingPremultiplied;
+      break;
+    case HWC2::BlendMode::None:
+      blending = kBlendingOpaque;
+      break;
+    default:
+      return HWC2::Error::BadParameter;
+  }
+
+  if (layer_->blending != blending) {
+    geometry_changes_ |= kBlendMode;
+    layer_->blending = blending;
+  }
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerColor(hwc_color_t color) {
+  layer_->solid_fill_color = GetUint32Color(color);
+  layer_->input_buffer.format = kFormatARGB8888;
+  DLOGV_IF(kTagCompManager, "[%" PRIu64 "][%" PRIu64 "] Layer color set to %x", display_id_, id_,
+           layer_->solid_fill_color);
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerCompositionType(HWC2::Composition type) {
+  client_requested_ = type;
+  switch (type) {
+    case HWC2::Composition::Client:
+      break;
+    case HWC2::Composition::Device:
+      // We try and default to this in SDM
+      break;
+    case HWC2::Composition::SolidColor:
+      break;
+    case HWC2::Composition::Cursor:
+      break;
+    case HWC2::Composition::Invalid:
+      return HWC2::Error::BadParameter;
+    default:
+      return HWC2::Error::Unsupported;
+  }
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerDataspace(int32_t dataspace) {
+  // Map deprecated dataspace values to appropriate
+  // new enums
+  if (dataspace & 0xffff) {
+    switch (dataspace & 0xffff) {
+      case HAL_DATASPACE_SRGB:
+        dataspace = HAL_DATASPACE_V0_SRGB;
+        break;
+      case HAL_DATASPACE_JFIF:
+        dataspace = HAL_DATASPACE_V0_JFIF;
+        break;
+      case HAL_DATASPACE_SRGB_LINEAR:
+        dataspace = HAL_DATASPACE_V0_SRGB_LINEAR;
+        break;
+      case HAL_DATASPACE_BT601_625:
+        dataspace = HAL_DATASPACE_V0_BT601_625;
+        break;
+      case HAL_DATASPACE_BT601_525:
+        dataspace = HAL_DATASPACE_V0_BT601_525;
+        break;
+      case HAL_DATASPACE_BT709:
+        dataspace = HAL_DATASPACE_V0_BT709;
+        break;
+      default:
+        // unknown legacy dataspace
+        DLOGW_IF(kTagQDCM, "Unsupported dataspace type %d", dataspace);
+    }
+  }
+
+  if (dataspace_ != dataspace) {
+    geometry_changes_ |= kDataspace;
+    dataspace_ = dataspace;
+  }
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerDisplayFrame(hwc_rect_t frame) {
+  LayerRect dst_rect = {};
+
+  SetRect(frame, &dst_rect);
+  if (dst_rect_ != dst_rect) {
+    geometry_changes_ |= kDisplayFrame;
+    dst_rect_ = dst_rect;
+  }
+
+  return HWC2::Error::None;
+}
+
+void HWCLayer::ResetPerFrameData() {
+  layer_->dst_rect = dst_rect_;
+  layer_->transform = layer_transform_;
+}
+
+HWC2::Error HWCLayer::SetLayerPlaneAlpha(float alpha) {
+  // Conversion of float alpha in range 0.0 to 1.0 similar to the HWC Adapter
+  uint8_t plane_alpha = static_cast<uint8_t>(std::round(255.0f * alpha));
+  if (layer_->plane_alpha != plane_alpha) {
+    geometry_changes_ |= kPlaneAlpha;
+    layer_->plane_alpha = plane_alpha;
+  }
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerSourceCrop(hwc_frect_t crop) {
+  LayerRect src_rect = {};
+  SetRect(crop, &src_rect);
+  if (layer_->src_rect != src_rect) {
+    geometry_changes_ |= kSourceCrop;
+    layer_->src_rect = src_rect;
+  }
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerTransform(HWC2::Transform transform) {
+  LayerTransform layer_transform = {};
+  switch (transform) {
+    case HWC2::Transform::FlipH:
+      layer_transform.flip_horizontal = true;
+      break;
+    case HWC2::Transform::FlipV:
+      layer_transform.flip_vertical = true;
+      break;
+    case HWC2::Transform::Rotate90:
+      layer_transform.rotation = 90.0f;
+      break;
+    case HWC2::Transform::Rotate180:
+      layer_transform.flip_horizontal = true;
+      layer_transform.flip_vertical = true;
+      break;
+    case HWC2::Transform::Rotate270:
+      layer_transform.rotation = 90.0f;
+      layer_transform.flip_horizontal = true;
+      layer_transform.flip_vertical = true;
+      break;
+    case HWC2::Transform::FlipHRotate90:
+      layer_transform.rotation = 90.0f;
+      layer_transform.flip_horizontal = true;
+      break;
+    case HWC2::Transform::FlipVRotate90:
+      layer_transform.rotation = 90.0f;
+      layer_transform.flip_vertical = true;
+      break;
+    case HWC2::Transform::None:
+      // do nothing
+      break;
+  }
+
+  if (layer_transform_ != layer_transform) {
+    geometry_changes_ |= kTransform;
+    layer_transform_ = layer_transform;
+  }
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerVisibleRegion(hwc_region_t visible) {
+  layer_->visible_regions.clear();
+  for (uint32_t i = 0; i < visible.numRects; i++) {
+    LayerRect rect;
+    SetRect(visible.rects[i], &rect);
+    layer_->visible_regions.push_back(rect);
+  }
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerZOrder(uint32_t z) {
+  if (z_ != z) {
+    geometry_changes_ |= kZOrder;
+    z_ = z;
+  }
+  return HWC2::Error::None;
+}
+
+void HWCLayer::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 HWCLayer::SetRect(const hwc_frect_t &source, LayerRect *target) {
+  // Recommended way of rounding as in hwcomposer2.h - SetLayerSourceCrop
+  target->left = std::ceil(source.left);
+  target->top = std::ceil(source.top);
+  target->right = std::floor(source.right);
+  target->bottom = std::floor(source.bottom);
+}
+
+uint32_t HWCLayer::GetUint32Color(const hwc_color_t &source) {
+  // Returns 32 bit ARGB
+  uint32_t a = UINT32(source.a) << 24;
+  uint32_t r = UINT32(source.r) << 16;
+  uint32_t g = UINT32(source.g) << 8;
+  uint32_t b = UINT32(source.b);
+  uint32_t color = a | r | g | b;
+  return color;
+}
+
+LayerBufferFormat HWCLayer::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_BGR_565:
+        format = kFormatBGR565Ubwc;
+        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;
+      case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+        format = kFormatYCbCr420TP10Ubwc;
+        break;
+      case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+        format = kFormatYCbCr420P010Ubwc;
+        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_BGR_888:
+      format = kFormatBGR888;
+      break;
+    case HAL_PIXEL_FORMAT_RGB_565:
+      format = kFormatRGB565;
+      break;
+    case HAL_PIXEL_FORMAT_BGR_565:
+      format = kFormatBGR565;
+      break;
+    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+      format = kFormatYCbCr420SemiPlanarVenus;
+      break;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+      format = kFormatYCrCb420SemiPlanarVenus;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+      format = kFormatYCbCr420SPVenusUbwc;
+      break;
+    case HAL_PIXEL_FORMAT_YV12:
+      format = kFormatYCrCb420PlanarStride16;
+      break;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+      format = kFormatYCrCb420SemiPlanar;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+      format = kFormatYCbCr420SemiPlanar;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+      format = kFormatYCbCr422H2V1SemiPlanar;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_422_I:
+      format = kFormatYCbCr422H2V1Packed;
+      break;
+    case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+      format = kFormatCbYCrY422H2V1Packed;
+      break;
+    case HAL_PIXEL_FORMAT_RGBA_1010102:
+      format = kFormatRGBA1010102;
+      break;
+    case HAL_PIXEL_FORMAT_ARGB_2101010:
+      format = kFormatARGB2101010;
+      break;
+    case HAL_PIXEL_FORMAT_RGBX_1010102:
+      format = kFormatRGBX1010102;
+      break;
+    case HAL_PIXEL_FORMAT_XRGB_2101010:
+      format = kFormatXRGB2101010;
+      break;
+    case HAL_PIXEL_FORMAT_BGRA_1010102:
+      format = kFormatBGRA1010102;
+      break;
+    case HAL_PIXEL_FORMAT_ABGR_2101010:
+      format = kFormatABGR2101010;
+      break;
+    case HAL_PIXEL_FORMAT_BGRX_1010102:
+      format = kFormatBGRX1010102;
+      break;
+    case HAL_PIXEL_FORMAT_XBGR_2101010:
+      format = kFormatXBGR2101010;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+      format = kFormatYCbCr420P010;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+      format = kFormatYCbCr420TP10Ubwc;
+      break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+      format = kFormatYCbCr420P010Ubwc;
+      break;
+    default:
+      DLOGW("Unsupported format type = %d", source);
+      return kFormatInvalid;
+  }
+
+  return format;
+}
+
+LayerBufferS3DFormat HWCLayer::GetS3DFormat(uint32_t s3d_format) {
+  LayerBufferS3DFormat sdm_s3d_format = kS3dFormatNone;
+  switch (s3d_format) {
+    case HAL_NO_3D:
+      sdm_s3d_format = kS3dFormatNone;
+      break;
+    case HAL_3D_SIDE_BY_SIDE_L_R:
+      sdm_s3d_format = kS3dFormatLeftRight;
+      break;
+    case HAL_3D_SIDE_BY_SIDE_R_L:
+      sdm_s3d_format = kS3dFormatRightLeft;
+      break;
+    case HAL_3D_TOP_BOTTOM:
+      sdm_s3d_format = kS3dFormatTopBottom;
+      break;
+    default:
+      DLOGW("Invalid S3D format %d", s3d_format);
+  }
+  return sdm_s3d_format;
+}
+
+DisplayError HWCLayer::SetMetaData(const private_handle_t *pvt_handle, Layer *layer) {
+  LayerBuffer *layer_buffer = &layer->input_buffer;
+  bool use_color_metadata = true;
+
+#ifdef FEATURE_WIDE_COLOR
+  // Only use color metadata if Android framework metadata is not set
+  use_color_metadata = (dataspace_ == HAL_DATASPACE_UNKNOWN);
+#endif
+
+  if (use_color_metadata) {
+    if (sdm::SetCSC(pvt_handle, &layer_buffer->color_metadata) != kErrorNone) {
+      return kErrorNotSupported;
+    }
+  }
+
+  private_handle_t *handle = const_cast<private_handle_t *>(pvt_handle);
+  IGC_t igc = {};
+  if (getMetaData(handle, GET_IGC, &igc) == 0) {
+    if (SetIGC(igc, &layer_buffer->igc) != kErrorNone) {
+      return kErrorNotSupported;
+    }
+  }
+
+  uint32_t fps = 0;
+  if (getMetaData(handle, GET_REFRESH_RATE  , &fps) == 0) {
+    layer->frame_rate = RoundToStandardFPS(fps);
+  }
+
+  int32_t interlaced = 0;
+  if (getMetaData(handle, GET_PP_PARAM_INTERLACED, &interlaced) == 0) {
+    layer_buffer->flags.interlace = interlaced ? true : false;
+  }
+
+  uint32_t linear_format = 0;
+  if (getMetaData(handle, GET_LINEAR_FORMAT, &linear_format) == 0) {
+    layer_buffer->format = GetSDMFormat(INT32(linear_format), 0);
+  }
+
+  uint32_t s3d = 0;
+  if (getMetaData(handle, GET_S3D_FORMAT, &s3d) == 0) {
+    layer_buffer->s3d_format = GetS3DFormat(s3d);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWCLayer::SetIGC(IGC_t source, LayerIGC *target) {
+  switch (source) {
+    case IGC_NotSpecified:
+      *target = kIGCNotSpecified;
+      break;
+    case IGC_sRGB:
+      *target = kIGCsRGB;
+      break;
+    default:
+      DLOGE("Unsupported IGC: %d", source);
+      return kErrorNotSupported;
+  }
+
+  return kErrorNone;
+}
+
+
+
+bool HWCLayer::SupportLocalConversion(ColorPrimaries working_primaries) {
+  if (layer_->input_buffer.color_metadata.colorPrimaries <= ColorPrimaries_BT601_6_525 &&
+      working_primaries <= ColorPrimaries_BT601_6_525) {
+    return true;
+  }
+  return false;
+}
+
+bool HWCLayer::SupportedDataspace() {
+  if (dataspace_ == HAL_DATASPACE_UNKNOWN) {
+    // Pick values from metadata
+    return true;
+  }
+
+  LayerBuffer *layer_buffer = &layer_->input_buffer;
+
+  GammaTransfer sdm_transfer = {};
+  ColorPrimaries sdm_primaries = {};
+  ColorRange sdm_range = {};
+
+  auto transfer = dataspace_ & HAL_DATASPACE_TRANSFER_MASK;
+  // Handle transfer
+  switch (transfer) {
+    case HAL_DATASPACE_TRANSFER_SRGB:
+      sdm_transfer = Transfer_sRGB;
+      break;
+    case HAL_DATASPACE_TRANSFER_SMPTE_170M:
+      sdm_transfer = Transfer_SMPTE_170M;
+      break;
+    case HAL_DATASPACE_TRANSFER_ST2084:
+      sdm_transfer = Transfer_SMPTE_ST2084;
+      break;
+    case HAL_DATASPACE_TRANSFER_HLG:
+      sdm_transfer = Transfer_HLG;
+      break;
+    case HAL_DATASPACE_TRANSFER_LINEAR:
+      sdm_transfer = Transfer_Linear;
+      break;
+    case HAL_DATASPACE_TRANSFER_GAMMA2_2:
+      sdm_transfer = Transfer_Gamma2_2;
+      break;
+    default:
+      return false;
+  }
+
+  // Handle standard
+  auto standard = dataspace_ & HAL_DATASPACE_STANDARD_MASK;
+  switch (standard) {
+    case  HAL_DATASPACE_STANDARD_BT709:
+      sdm_primaries = ColorPrimaries_BT709_5;
+      break;
+    case HAL_DATASPACE_STANDARD_BT601_525:
+    case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
+      sdm_primaries = ColorPrimaries_BT601_6_525;
+      break;
+    case HAL_DATASPACE_STANDARD_BT601_625:
+    case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
+      sdm_primaries = ColorPrimaries_BT601_6_625;
+      break;
+    case HAL_DATASPACE_STANDARD_DCI_P3:
+      sdm_primaries = ColorPrimaries_DCIP3;
+      break;
+    case HAL_DATASPACE_STANDARD_BT2020:
+      sdm_primaries = ColorPrimaries_BT2020;
+      break;
+    default:
+      return false;
+  }
+  // TODO(user): Check transfer + primary combination
+
+  // Handle range
+  auto range = dataspace_ & HAL_DATASPACE_RANGE_MASK;
+  switch (range) {
+    case HAL_DATASPACE_RANGE_FULL:
+      sdm_range = Range_Full;
+      break;
+    case HAL_DATASPACE_RANGE_LIMITED:
+    default:
+      sdm_range = Range_Limited;
+      break;
+  }
+
+  // If we got here, the value is supported, update the layer
+  layer_buffer->color_metadata.transfer = sdm_transfer;
+  layer_buffer->color_metadata.colorPrimaries = sdm_primaries;
+  layer_buffer->color_metadata.range = sdm_range;
+  return true;
+}
+
+
+uint32_t HWCLayer::RoundToStandardFPS(float fps) {
+  static const uint32_t standard_fps[4] = {24, 30, 48, 60};
+  uint32_t frame_rate = (uint32_t)(fps);
+
+  int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
+  for (int i = 0; i < count; i++) {
+    if ((standard_fps[i] - frame_rate) < 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 frame_rate;
+}
+
+void HWCLayer::SetComposition(const LayerComposition &sdm_composition) {
+  auto hwc_composition = HWC2::Composition::Invalid;
+  switch (sdm_composition) {
+    case kCompositionGPU:
+      hwc_composition = HWC2::Composition::Client;
+      break;
+    case kCompositionCursor:
+      hwc_composition = HWC2::Composition::Cursor;
+      break;
+    default:
+      hwc_composition = HWC2::Composition::Device;
+      break;
+  }
+  // Update solid fill composition
+  if (sdm_composition == kCompositionSDE && layer_->flags.solid_fill != 0) {
+    hwc_composition = HWC2::Composition::SolidColor;
+  }
+  device_selected_ = hwc_composition;
+
+  return;
+}
+void HWCLayer::PushReleaseFence(int32_t fence) {
+  release_fences_.push(fence);
+}
+int32_t HWCLayer::PopReleaseFence(void) {
+  if (release_fences_.empty())
+    return -1;
+  auto fence = release_fences_.front();
+  release_fences_.pop();
+  return fence;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc2/hwc_layers.h b/sdm845/sdm/libs/hwc2/hwc_layers.h
new file mode 100644
index 0000000..f536cb7
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_layers.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HWC_LAYERS_H__
+#define __HWC_LAYERS_H__
+
+/* This class translates HWC2 Layer functions to the SDM LayerStack
+ */
+
+#include <gralloc_priv.h>
+#include <qdMetaData.h>
+#include <core/layer_stack.h>
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+#include <map>
+#include <queue>
+#include <set>
+#include "core/buffer_allocator.h"
+#include "hwc_buffer_allocator.h"
+
+namespace sdm {
+
+DisplayError SetCSC(const private_handle_t *pvt_handle, ColorMetaData *color_metadata);
+
+enum GeometryChanges {
+  kNone         = 0x000,
+  kBlendMode    = 0x001,
+  kDataspace    = 0x002,
+  kDisplayFrame = 0x004,
+  kPlaneAlpha   = 0x008,
+  kSourceCrop   = 0x010,
+  kTransform    = 0x020,
+  kZOrder       = 0x040,
+  kAdded        = 0x080,
+  kRemoved      = 0x100,
+};
+
+class HWCLayer {
+ public:
+  explicit HWCLayer(hwc2_display_t display_id, HWCBufferAllocator *buf_allocator);
+  ~HWCLayer();
+  uint32_t GetZ() const { return z_; }
+  hwc2_layer_t GetId() const { return id_; }
+  Layer *GetSDMLayer() { return layer_; }
+  void ResetPerFrameData();
+
+  HWC2::Error SetLayerBlendMode(HWC2::BlendMode mode);
+  HWC2::Error SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence);
+  HWC2::Error SetLayerColor(hwc_color_t color);
+  HWC2::Error SetLayerCompositionType(HWC2::Composition type);
+  HWC2::Error SetLayerDataspace(int32_t dataspace);
+  HWC2::Error SetLayerDisplayFrame(hwc_rect_t frame);
+  HWC2::Error SetLayerPlaneAlpha(float alpha);
+  HWC2::Error SetLayerSourceCrop(hwc_frect_t crop);
+  HWC2::Error SetLayerSurfaceDamage(hwc_region_t damage);
+  HWC2::Error SetLayerTransform(HWC2::Transform transform);
+  HWC2::Error SetLayerVisibleRegion(hwc_region_t visible);
+  HWC2::Error SetLayerZOrder(uint32_t z);
+  void SetComposition(const LayerComposition &sdm_composition);
+  HWC2::Composition GetClientRequestedCompositionType() { return client_requested_; }
+  void UpdateClientCompositionType(HWC2::Composition type) { client_requested_ = type; }
+  HWC2::Composition GetDeviceSelectedCompositionType() { return device_selected_; }
+  int32_t GetLayerDataspace() { return dataspace_; }
+  uint32_t GetGeometryChanges() { return geometry_changes_; }
+  void ResetGeometryChanges() { geometry_changes_ = GeometryChanges::kNone; }
+  void PushReleaseFence(int32_t fence);
+  int32_t PopReleaseFence(void);
+  bool SupportedDataspace();
+  bool SupportLocalConversion(ColorPrimaries working_primaries);
+
+ private:
+  Layer *layer_ = nullptr;
+  uint32_t z_ = 0;
+  const hwc2_layer_t id_;
+  const hwc2_display_t display_id_;
+  static std::atomic<hwc2_layer_t> next_id_;
+  std::queue<int32_t> release_fences_;
+  int ion_fd_ = -1;
+  HWCBufferAllocator *buffer_allocator_ = NULL;
+  int32_t dataspace_ =  HAL_DATASPACE_UNKNOWN;
+  LayerTransform layer_transform_ = {};
+  LayerRect dst_rect_ = {};
+
+  // Composition requested by client(SF)
+  HWC2::Composition client_requested_ = HWC2::Composition::Device;
+  // Composition selected by SDM
+  HWC2::Composition device_selected_ = HWC2::Composition::Device;
+  uint32_t geometry_changes_ = GeometryChanges::kNone;
+
+  void SetRect(const hwc_rect_t &source, LayerRect *target);
+  void SetRect(const hwc_frect_t &source, LayerRect *target);
+  uint32_t GetUint32Color(const hwc_color_t &source);
+  LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
+  LayerBufferS3DFormat GetS3DFormat(uint32_t s3d_format);
+  DisplayError SetMetaData(const private_handle_t *pvt_handle, Layer *layer);
+  DisplayError SetIGC(IGC_t source, LayerIGC *target);
+  uint32_t RoundToStandardFPS(float fps);
+};
+
+struct SortLayersByZ {
+  bool operator()(const HWCLayer *lhs, const HWCLayer *rhs) const {
+    return lhs->GetZ() < rhs->GetZ();
+  }
+};
+
+}  // namespace sdm
+#endif  // __HWC_LAYERS_H__
diff --git a/sdm845/sdm/libs/hwc2/hwc_session.cpp b/sdm845/sdm/libs/hwc2/hwc_session.cpp
new file mode 100644
index 0000000..2bf7d4d
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_session.cpp
@@ -0,0 +1,1628 @@
+/*
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <core/dump_interface.h>
+#include <core/buffer_allocator.h>
+#include <private/color_params.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 <display_config.h>
+#include <utils/debug.h>
+#include <sync/sync.h>
+#include <profiler.h>
+#include <algorithm>
+#include <string>
+#include <bitset>
+
+#include "hwc_buffer_allocator.h"
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_session.h"
+#include "hwc_debugger.h"
+#include "hwc_display_primary.h"
+#include "hwc_display_virtual.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 = 3,
+    .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_;
+
+HWCSession::HWCSession(const hw_module_t *module) {
+  hwc2_device_t::common.tag = HARDWARE_DEVICE_TAG;
+  hwc2_device_t::common.version = HWC_DEVICE_API_VERSION_2_0;
+  hwc2_device_t::common.module = const_cast<hw_module_t *>(module);
+  hwc2_device_t::common.close = Close;
+  hwc2_device_t::getCapabilities = GetCapabilities;
+  hwc2_device_t::getFunction = GetFunction;
+}
+
+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> iqservice = android::interface_cast<qService::IQService>(
+      android::defaultServiceManager()->getService(android::String16(qservice_name)));
+
+  if (iqservice.get()) {
+    iqservice->connect(android::sp<qClient::IQClient>(this));
+    qservice_ = reinterpret_cast<qService::QService *>(iqservice.get());
+  } else {
+    DLOGE("Failed to acquire %s", qservice_name);
+    return -EINVAL;
+  }
+
+  buffer_allocator_ = new HWCBufferAllocator();
+
+  DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), buffer_allocator_,
+                                                 &buffer_sync_handler_, &socket_handler_,
+                                                 &core_intf_);
+  if (error != kErrorNone) {
+    DLOGE("Display core initialization failed. Error = %d", error);
+    return -EINVAL;
+  }
+
+  // Read which display is first, and create it and store it in primary slot
+  // TODO(user): This will need to be redone for HWC2 - right now we validate only
+  // the primary physical path
+  HWDisplayInterfaceInfo hw_disp_info;
+  error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
+  if (error == kErrorNone && hw_disp_info.type == kHDMI && hw_disp_info.is_connected) {
+    // HDMI is primary display. If already connected, then create it and store in
+    // primary display slot. If not connected, create a NULL display for now.
+    status = HWCDisplayExternal::Create(core_intf_, buffer_allocator_, &callbacks_, qservice_,
+                                        &hwc_display_[HWC_DISPLAY_PRIMARY]);
+  } else {
+    // Create and power on primary display
+    status = HWCDisplayPrimary::Create(core_intf_, buffer_allocator_, &callbacks_, qservice_,
+                                       &hwc_display_[HWC_DISPLAY_PRIMARY]);
+  }
+
+  if (status) {
+    CoreInterface::DestroyCore();
+    return status;
+  }
+
+  color_mgr_ = HWCColorManager::CreateColorManager(buffer_allocator_);
+  if (!color_mgr_) {
+    DLOGW("Failed to load HWCColorManager.");
+  }
+
+  if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) {
+    DLOGE("Failed to start = %s, error = %s", uevent_thread_name_, strerror(errno));
+    HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
+    hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
+    CoreInterface::DestroyCore();
+    return -errno;
+  }
+
+  struct rlimit fd_limit = {};
+  getrlimit(RLIMIT_NOFILE, &fd_limit);
+  fd_limit.rlim_cur = fd_limit.rlim_cur * 2;
+  if (fd_limit.rlim_cur < fd_limit.rlim_max) {
+    auto err = setrlimit(RLIMIT_NOFILE, &fd_limit);
+    if (err) {
+      DLOGW("Unable to increase fd limit -  err:%d, %s", errno, strerror(errno));
+    }
+  }
+  return 0;
+}
+
+int HWCSession::Deinit() {
+  HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
+  hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
+  if (color_mgr_) {
+    color_mgr_->DestroyColorManager();
+  }
+  uevent_thread_exit_ = true;
+  DLOGD("Terminating uevent thread");
+  // TODO(user): on restarting HWC in the same process, the uevent thread does not restart
+  // cleanly.
+  Sys::pthread_cancel_(uevent_thread_);
+
+  DisplayError error = CoreInterface::DestroyCore();
+  if (error != kErrorNone) {
+    DLOGE("Display core de-initialization failed. Error = %d", error);
+  }
+
+  if (buffer_allocator_ != nullptr) {
+    delete buffer_allocator_;
+  }
+  buffer_allocator_ = nullptr;
+
+  return 0;
+}
+
+int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  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) {
+      return status;
+    }
+
+    hwc2_device_t *composer_device = hwc_session;
+    *device = reinterpret_cast<hw_device_t *>(composer_device);
+  }
+
+  return 0;
+}
+
+int HWCSession::Close(hw_device_t *device) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  if (!device) {
+    return -EINVAL;
+  }
+
+  hwc2_device_t *composer_device = reinterpret_cast<hwc2_device_t *>(device);
+  HWCSession *hwc_session = static_cast<HWCSession *>(composer_device);
+
+  hwc_session->Deinit();
+
+  return 0;
+}
+
+void HWCSession::GetCapabilities(struct hwc2_device *device, uint32_t *outCount,
+                                 int32_t *outCapabilities) {
+  if (outCapabilities != nullptr && *outCount >= 1) {
+    outCapabilities[0] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
+  }
+  *outCount = 1;
+}
+
+template <typename PFN, typename T>
+static hwc2_function_pointer_t AsFP(T function) {
+  static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
+  return reinterpret_cast<hwc2_function_pointer_t>(function);
+}
+
+// HWC2 functions returned in GetFunction
+// Defined in the same order as in the HWC2 header
+
+int32_t HWCSession::AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display) {
+  SCOPE_LOCK(locker_);
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::AcceptDisplayChanges);
+}
+
+int32_t HWCSession::CreateLayer(hwc2_device_t *device, hwc2_display_t display,
+                                hwc2_layer_t *out_layer_id) {
+  SCOPE_LOCK(locker_);
+  return CallDisplayFunction(device, display, &HWCDisplay::CreateLayer, out_layer_id);
+}
+
+int32_t HWCSession::CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height,
+                                         int32_t *format, hwc2_display_t *out_display_id) {
+  // TODO(user): Handle concurrency with HDMI
+  SCOPE_LOCK(locker_);
+  if (!device) {
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  auto status = hwc_session->CreateVirtualDisplayObject(width, height, format);
+  if (status == HWC2::Error::None) {
+    *out_display_id = HWC_DISPLAY_VIRTUAL;
+    DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d",
+          *out_display_id, width, height);
+  } else {
+    DLOGE("Failed to create virtual display: %s", to_string(status).c_str());
+  }
+  return INT32(status);
+}
+
+int32_t HWCSession::DestroyLayer(hwc2_device_t *device, hwc2_display_t display,
+                                 hwc2_layer_t layer) {
+  SCOPE_LOCK(locker_);
+  return CallDisplayFunction(device, display, &HWCDisplay::DestroyLayer, layer);
+}
+
+int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) {
+  SCOPE_LOCK(locker_);
+  if (!device) {
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+
+  DLOGI("Destroying virtual display id:%" PRIu64, display);
+  auto *hwc_session = static_cast<HWCSession *>(device);
+
+  if (hwc_session->hwc_display_[display]) {
+    HWCDisplayVirtual::Destroy(hwc_session->hwc_display_[display]);
+    hwc_session->hwc_display_[display] = nullptr;
+    return HWC2_ERROR_NONE;
+  } else {
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+}
+
+void HWCSession::Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  if (!device) {
+    return;
+  }
+  auto *hwc_session = static_cast<HWCSession *>(device);
+  const size_t max_dump_size = 8192;
+
+  if (out_buffer == nullptr) {
+    *out_size = max_dump_size;
+  } else {
+    char sdm_dump[4096];
+    DumpInterface::GetDump(sdm_dump, 4096);  // TODO(user): Fix this workaround
+    std::string s("");
+    for (int id = HWC_DISPLAY_PRIMARY; id <= HWC_DISPLAY_VIRTUAL; id++) {
+      if (hwc_session->hwc_display_[id]) {
+        s += hwc_session->hwc_display_[id]->Dump();
+      }
+    }
+    s += sdm_dump;
+    auto copied = s.copy(out_buffer, std::min(s.size(), max_dump_size), 0);
+    *out_size = UINT32(copied);
+  }
+}
+
+static int32_t GetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
+                               hwc2_config_t *out_config) {
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetActiveConfig, out_config);
+}
+
+static int32_t GetChangedCompositionTypes(hwc2_device_t *device, hwc2_display_t display,
+                                          uint32_t *out_num_elements, hwc2_layer_t *out_layers,
+                                          int32_t *out_types) {
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetChangedCompositionTypes,
+                                         out_num_elements, out_layers, out_types);
+}
+
+static int32_t GetClientTargetSupport(hwc2_device_t *device, hwc2_display_t display, uint32_t width,
+                                      uint32_t height, int32_t format, int32_t dataspace) {
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetClientTargetSupport,
+                                         width, height, format, dataspace);
+}
+
+static int32_t GetColorModes(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_num_modes,
+                             int32_t /*android_color_mode_t*/ *int_out_modes) {
+  auto out_modes = reinterpret_cast<android_color_mode_t *>(int_out_modes);
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetColorModes, out_num_modes,
+                                         out_modes);
+}
+
+static int32_t GetDisplayAttribute(hwc2_device_t *device, hwc2_display_t display,
+                                   hwc2_config_t config, int32_t int_attribute,
+                                   int32_t *out_value) {
+  auto attribute = static_cast<HWC2::Attribute>(int_attribute);
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayAttribute, config,
+                                         attribute, out_value);
+}
+
+static int32_t GetDisplayConfigs(hwc2_device_t *device, hwc2_display_t display,
+                                 uint32_t *out_num_configs, hwc2_config_t *out_configs) {
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayConfigs,
+                                         out_num_configs, out_configs);
+}
+
+static int32_t GetDisplayName(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_size,
+                              char *out_name) {
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayName, out_size,
+                                         out_name);
+}
+
+static int32_t GetDisplayRequests(hwc2_device_t *device, hwc2_display_t display,
+                                  int32_t *out_display_requests, uint32_t *out_num_elements,
+                                  hwc2_layer_t *out_layers, int32_t *out_layer_requests) {
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayRequests,
+                                         out_display_requests, out_num_elements, out_layers,
+                                         out_layer_requests);
+}
+
+static int32_t GetDisplayType(hwc2_device_t *device, hwc2_display_t display, int32_t *out_type) {
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayType, out_type);
+}
+
+static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display, int32_t *out_support) {
+  if (display == HWC_DISPLAY_PRIMARY) {
+    *out_support = 1;
+  } else {
+    // TODO(user): Port over connect_display_ from HWC1
+    // Return no error for connected displays
+    *out_support = 0;
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+  return HWC2_ERROR_NONE;
+}
+
+static int32_t GetHdrCapabilities(hwc2_device_t* device, hwc2_display_t display,
+                                  uint32_t* out_num_types, int32_t* out_types,
+                                  float* out_max_luminance, float* out_max_average_luminance,
+                                  float* out_min_luminance) {
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetHdrCapabilities,
+                                         out_num_types, out_types, out_max_luminance,
+                                         out_max_average_luminance, out_min_luminance);
+}
+
+static uint32_t GetMaxVirtualDisplayCount(hwc2_device_t *device) {
+  return 1;
+}
+
+static int32_t GetReleaseFences(hwc2_device_t *device, hwc2_display_t display,
+                                uint32_t *out_num_elements, hwc2_layer_t *out_layers,
+                                int32_t *out_fences) {
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetReleaseFences,
+                                         out_num_elements, out_layers, out_fences);
+}
+
+int32_t HWCSession::PresentDisplay(hwc2_device_t *device, hwc2_display_t display,
+                                   int32_t *out_retire_fence) {
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  DTRACE_SCOPED();
+  SEQUENCE_EXIT_SCOPE_LOCK(locker_);
+  if (!device) {
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+
+  auto status = HWC2::Error::BadDisplay;
+  // TODO(user): Handle virtual display/HDMI concurrency
+  if (hwc_session->hwc_display_[display]) {
+    status = hwc_session->hwc_display_[display]->Present(out_retire_fence);
+    // This is only indicative of how many times SurfaceFlinger posts
+    // frames to the display.
+    CALC_FPS();
+  }
+
+  return INT32(status);
+}
+
+int32_t HWCSession::RegisterCallback(hwc2_device_t *device, int32_t descriptor,
+                                     hwc2_callback_data_t callback_data,
+                                     hwc2_function_pointer_t pointer) {
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  if (!device) {
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+  auto desc = static_cast<HWC2::Callback>(descriptor);
+  auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer);
+  DLOGD("Registering callback: %s", to_string(desc).c_str());
+  if (descriptor == HWC2_CALLBACK_HOTPLUG)
+    hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
+  return INT32(error);
+}
+
+static int32_t SetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
+                               hwc2_config_t config) {
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetActiveConfig, config);
+}
+
+static int32_t SetClientTarget(hwc2_device_t *device, hwc2_display_t display,
+                               buffer_handle_t target, int32_t acquire_fence,
+                               int32_t dataspace, hwc_region_t damage) {
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetClientTarget, target,
+                                         acquire_fence, dataspace, damage);
+}
+
+int32_t HWCSession::SetColorMode(hwc2_device_t *device, hwc2_display_t display,
+                                 int32_t /*android_color_mode_t*/ int_mode) {
+  auto mode = static_cast<android_color_mode_t>(int_mode);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
+}
+
+int32_t HWCSession::SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
+                                      const float *matrix,
+                                      int32_t /*android_color_transform_t*/ hint) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+  android_color_transform_t transform_hint = static_cast<android_color_transform_t>(hint);
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorTransform, matrix,
+                                         transform_hint);
+}
+
+static int32_t SetCursorPosition(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+                                 int32_t x, int32_t y) {
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetCursorPosition, layer, x,
+                                         y);
+}
+
+static int32_t SetLayerBlendMode(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+                                 int32_t int_mode) {
+  auto mode = static_cast<HWC2::BlendMode>(int_mode);
+  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBlendMode, mode);
+}
+
+static int32_t SetLayerBuffer(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+                              buffer_handle_t buffer, int32_t acquire_fence) {
+  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBuffer, buffer,
+                                       acquire_fence);
+}
+
+static int32_t SetLayerColor(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+                             hwc_color_t color) {
+  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerColor, color);
+}
+
+static int32_t SetLayerCompositionType(hwc2_device_t *device, hwc2_display_t display,
+                                       hwc2_layer_t layer, int32_t int_type) {
+  auto type = static_cast<HWC2::Composition>(int_type);
+  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerCompositionType,
+                                       type);
+}
+
+static int32_t SetLayerDataspace(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+                                 int32_t dataspace) {
+  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDataspace,
+                                       dataspace);
+}
+
+static int32_t SetLayerDisplayFrame(hwc2_device_t *device, hwc2_display_t display,
+                                    hwc2_layer_t layer, hwc_rect_t frame) {
+  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDisplayFrame,
+                                       frame);
+}
+
+static int32_t SetLayerPlaneAlpha(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+                                  float alpha) {
+  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerPlaneAlpha,
+                                       alpha);
+}
+
+static int32_t SetLayerSourceCrop(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+                                  hwc_frect_t crop) {
+  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSourceCrop, crop);
+}
+
+static int32_t SetLayerSurfaceDamage(hwc2_device_t *device, hwc2_display_t display,
+                                     hwc2_layer_t layer, hwc_region_t damage) {
+  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSurfaceDamage,
+                                       damage);
+}
+
+static int32_t SetLayerTransform(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+                                 int32_t int_transform) {
+  auto transform = static_cast<HWC2::Transform>(int_transform);
+  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerTransform,
+                                       transform);
+}
+
+static int32_t SetLayerVisibleRegion(hwc2_device_t *device, hwc2_display_t display,
+                                     hwc2_layer_t layer, hwc_region_t visible) {
+  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerVisibleRegion,
+                                       visible);
+}
+
+int32_t HWCSession::SetLayerZOrder(hwc2_device_t *device, hwc2_display_t display,
+                                   hwc2_layer_t layer, uint32_t z) {
+  SCOPE_LOCK(locker_);
+  return CallDisplayFunction(device, display, &HWCDisplay::SetLayerZOrder, layer, z);
+}
+
+int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display,
+                                    buffer_handle_t buffer, int32_t releaseFence) {
+  if (!device) {
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+
+  auto *hwc_session = static_cast<HWCSession *>(device);
+  if (display == HWC_DISPLAY_VIRTUAL && hwc_session->hwc_display_[display]) {
+    auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_session->hwc_display_[display]);
+    auto status = vds->SetOutputBuffer(buffer, releaseFence);
+    return INT32(status);
+  } else {
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+}
+
+int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) {
+  auto mode = static_cast<HWC2::PowerMode>(int_mode);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+  return CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode);
+}
+
+static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display, int32_t int_enabled) {
+  auto enabled = static_cast<HWC2::Vsync>(int_enabled);
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetVsyncEnabled, enabled);
+}
+
+int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
+                                    uint32_t *out_num_types, uint32_t *out_num_requests) {
+  DTRACE_SCOPED();
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  if (!device) {
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+
+  // TODO(user): Handle secure session, handle QDCM solid fill
+  // Handle external_pending_connect_ in CreateVirtualDisplay
+  auto status = HWC2::Error::BadDisplay;
+  if (hwc_session->hwc_display_[display]) {
+    SEQUENCE_ENTRY_SCOPE_LOCK(locker_);
+    if (display == HWC_DISPLAY_PRIMARY) {
+      // TODO(user): This can be moved to HWCDisplayPrimary
+      if (hwc_session->reset_panel_) {
+        DLOGW("panel is in bad state, resetting the panel");
+        hwc_session->ResetPanel();
+      }
+
+      if (hwc_session->need_invalidate_) {
+        hwc_session->callbacks_.Refresh(display);
+      }
+
+      if (hwc_session->color_mgr_) {
+        hwc_session->color_mgr_->SetColorModeDetailEnhancer(hwc_session->hwc_display_[display]);
+      }
+    }
+
+    status = hwc_session->hwc_display_[display]->Validate(out_num_types, out_num_requests);
+  }
+  // If validate fails, cancel the sequence lock so that other operations
+  // (such as Dump or SetPowerMode) may succeed without blocking on the condition
+  if (status == HWC2::Error::BadDisplay) {
+    SEQUENCE_CANCEL_SCOPE_LOCK(locker_);
+  }
+  return INT32(status);
+}
+
+hwc2_function_pointer_t HWCSession::GetFunction(struct hwc2_device *device,
+                                                int32_t int_descriptor) {
+  auto descriptor = static_cast<HWC2::FunctionDescriptor>(int_descriptor);
+
+  switch (descriptor) {
+    case HWC2::FunctionDescriptor::AcceptDisplayChanges:
+      return AsFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(HWCSession::AcceptDisplayChanges);
+    case HWC2::FunctionDescriptor::CreateLayer:
+      return AsFP<HWC2_PFN_CREATE_LAYER>(CreateLayer);
+    case HWC2::FunctionDescriptor::CreateVirtualDisplay:
+      return AsFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(HWCSession::CreateVirtualDisplay);
+    case HWC2::FunctionDescriptor::DestroyLayer:
+      return AsFP<HWC2_PFN_DESTROY_LAYER>(DestroyLayer);
+    case HWC2::FunctionDescriptor::DestroyVirtualDisplay:
+      return AsFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(HWCSession::DestroyVirtualDisplay);
+    case HWC2::FunctionDescriptor::Dump:
+      return AsFP<HWC2_PFN_DUMP>(HWCSession::Dump);
+    case HWC2::FunctionDescriptor::GetActiveConfig:
+      return AsFP<HWC2_PFN_GET_ACTIVE_CONFIG>(GetActiveConfig);
+    case HWC2::FunctionDescriptor::GetChangedCompositionTypes:
+      return AsFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(GetChangedCompositionTypes);
+    case HWC2::FunctionDescriptor::GetClientTargetSupport:
+      return AsFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(GetClientTargetSupport);
+    case HWC2::FunctionDescriptor::GetColorModes:
+      return AsFP<HWC2_PFN_GET_COLOR_MODES>(GetColorModes);
+    case HWC2::FunctionDescriptor::GetDisplayAttribute:
+      return AsFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(GetDisplayAttribute);
+    case HWC2::FunctionDescriptor::GetDisplayConfigs:
+      return AsFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(GetDisplayConfigs);
+    case HWC2::FunctionDescriptor::GetDisplayName:
+      return AsFP<HWC2_PFN_GET_DISPLAY_NAME>(GetDisplayName);
+    case HWC2::FunctionDescriptor::GetDisplayRequests:
+      return AsFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(GetDisplayRequests);
+    case HWC2::FunctionDescriptor::GetDisplayType:
+      return AsFP<HWC2_PFN_GET_DISPLAY_TYPE>(GetDisplayType);
+    case HWC2::FunctionDescriptor::GetHdrCapabilities:
+      return AsFP<HWC2_PFN_GET_HDR_CAPABILITIES>(GetHdrCapabilities);
+    case HWC2::FunctionDescriptor::GetDozeSupport:
+      return AsFP<HWC2_PFN_GET_DOZE_SUPPORT>(GetDozeSupport);
+    case HWC2::FunctionDescriptor::GetMaxVirtualDisplayCount:
+      return AsFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(GetMaxVirtualDisplayCount);
+    case HWC2::FunctionDescriptor::GetReleaseFences:
+      return AsFP<HWC2_PFN_GET_RELEASE_FENCES>(GetReleaseFences);
+    case HWC2::FunctionDescriptor::PresentDisplay:
+      return AsFP<HWC2_PFN_PRESENT_DISPLAY>(PresentDisplay);
+    case HWC2::FunctionDescriptor::RegisterCallback:
+      return AsFP<HWC2_PFN_REGISTER_CALLBACK>(RegisterCallback);
+    case HWC2::FunctionDescriptor::SetActiveConfig:
+      return AsFP<HWC2_PFN_SET_ACTIVE_CONFIG>(SetActiveConfig);
+    case HWC2::FunctionDescriptor::SetClientTarget:
+      return AsFP<HWC2_PFN_SET_CLIENT_TARGET>(SetClientTarget);
+    case HWC2::FunctionDescriptor::SetColorMode:
+      return AsFP<HWC2_PFN_SET_COLOR_MODE>(SetColorMode);
+    case HWC2::FunctionDescriptor::SetColorTransform:
+      return AsFP<HWC2_PFN_SET_COLOR_TRANSFORM>(SetColorTransform);
+    case HWC2::FunctionDescriptor::SetCursorPosition:
+      return AsFP<HWC2_PFN_SET_CURSOR_POSITION>(SetCursorPosition);
+    case HWC2::FunctionDescriptor::SetLayerBlendMode:
+      return AsFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(SetLayerBlendMode);
+    case HWC2::FunctionDescriptor::SetLayerBuffer:
+      return AsFP<HWC2_PFN_SET_LAYER_BUFFER>(SetLayerBuffer);
+    case HWC2::FunctionDescriptor::SetLayerColor:
+      return AsFP<HWC2_PFN_SET_LAYER_COLOR>(SetLayerColor);
+    case HWC2::FunctionDescriptor::SetLayerCompositionType:
+      return AsFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(SetLayerCompositionType);
+    case HWC2::FunctionDescriptor::SetLayerDataspace:
+      return AsFP<HWC2_PFN_SET_LAYER_DATASPACE>(SetLayerDataspace);
+    case HWC2::FunctionDescriptor::SetLayerDisplayFrame:
+      return AsFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(SetLayerDisplayFrame);
+    case HWC2::FunctionDescriptor::SetLayerPlaneAlpha:
+      return AsFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(SetLayerPlaneAlpha);
+    // Sideband stream is not supported
+    // case HWC2::FunctionDescriptor::SetLayerSidebandStream:
+    case HWC2::FunctionDescriptor::SetLayerSourceCrop:
+      return AsFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(SetLayerSourceCrop);
+    case HWC2::FunctionDescriptor::SetLayerSurfaceDamage:
+      return AsFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(SetLayerSurfaceDamage);
+    case HWC2::FunctionDescriptor::SetLayerTransform:
+      return AsFP<HWC2_PFN_SET_LAYER_TRANSFORM>(SetLayerTransform);
+    case HWC2::FunctionDescriptor::SetLayerVisibleRegion:
+      return AsFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(SetLayerVisibleRegion);
+    case HWC2::FunctionDescriptor::SetLayerZOrder:
+      return AsFP<HWC2_PFN_SET_LAYER_Z_ORDER>(SetLayerZOrder);
+    case HWC2::FunctionDescriptor::SetOutputBuffer:
+      return AsFP<HWC2_PFN_SET_OUTPUT_BUFFER>(SetOutputBuffer);
+    case HWC2::FunctionDescriptor::SetPowerMode:
+      return AsFP<HWC2_PFN_SET_POWER_MODE>(SetPowerMode);
+    case HWC2::FunctionDescriptor::SetVsyncEnabled:
+      return AsFP<HWC2_PFN_SET_VSYNC_ENABLED>(SetVsyncEnabled);
+    case HWC2::FunctionDescriptor::ValidateDisplay:
+      return AsFP<HWC2_PFN_VALIDATE_DISPLAY>(HWCSession::ValidateDisplay);
+    default:
+      DLOGD("Unknown/Unimplemented function descriptor: %d (%s)", int_descriptor,
+            to_string(descriptor).c_str());
+      return nullptr;
+  }
+  return nullptr;
+}
+
+// TODO(user): handle locking
+
+HWC2::Error HWCSession::CreateVirtualDisplayObject(uint32_t width, uint32_t height,
+                                                   int32_t *format) {
+  if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+    return HWC2::Error::NoResources;
+  }
+  auto status = HWCDisplayVirtual::Create(core_intf_, buffer_allocator_, &callbacks_, width,
+                                          height, format, &hwc_display_[HWC_DISPLAY_VIRTUAL]);
+  // TODO(user): validate width and height support
+  if (status)
+    return HWC2::Error::Unsupported;
+
+  return HWC2::Error::None;
+}
+
+int32_t HWCSession::ConnectDisplay(int disp) {
+  DLOGI("Display = %d", disp);
+
+  int status = 0;
+  uint32_t primary_width = 0;
+  uint32_t primary_height = 0;
+
+  hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
+
+  if (disp == HWC_DISPLAY_EXTERNAL) {
+    status = HWCDisplayExternal::Create(core_intf_, buffer_allocator_, &callbacks_, primary_width,
+                                        primary_height, qservice_, false, &hwc_display_[disp]);
+  } else {
+    DLOGE("Invalid display type");
+    return -1;
+  }
+
+  if (!status) {
+    hwc_display_[disp]->SetSecureDisplay(secure_display_active_);
+  }
+
+  return status;
+}
+
+int HWCSession::DisconnectDisplay(int disp) {
+  DLOGI("Display = %d", disp);
+
+  if (disp == HWC_DISPLAY_EXTERNAL) {
+    HWCDisplayExternal::Destroy(hwc_display_[disp]);
+  } else if (disp == HWC_DISPLAY_VIRTUAL) {
+    HWCDisplayVirtual::Destroy(hwc_display_[disp]);
+  } else {
+    DLOGE("Invalid display type");
+    return -1;
+  }
+
+  hwc_display_[disp] = NULL;
+
+  return 0;
+}
+
+// Qclient methods
+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:
+      callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+      break;
+
+    case qService::IQService::SET_IDLE_TIMEOUT:
+      if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+        uint32_t timeout = UINT32(input_parcel->readInt32());
+        hwc_display_[HWC_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, output_parcel);
+      break;
+
+    case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
+      status = ConfigureRefreshRate(input_parcel);
+      break;
+
+    case qService::IQService::SET_VIEW_FRAME:
+      break;
+
+    case qService::IQService::TOGGLE_SCREEN_UPDATES:
+      status = ToggleScreenUpdates(input_parcel, output_parcel);
+      break;
+
+    case qService::IQService::QDCM_SVC_CMDS:
+      status = QdcmCMDHandler(input_parcel, output_parcel);
+      break;
+
+    case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED:
+      status = OnMinHdcpEncryptionLevelChange(input_parcel, output_parcel);
+      break;
+
+    case qService::IQService::CONTROL_PARTIAL_UPDATE:
+      status = ControlPartialUpdate(input_parcel, output_parcel);
+      break;
+
+    case qService::IQService::SET_ACTIVE_CONFIG:
+      status = HandleSetActiveDisplayConfig(input_parcel, output_parcel);
+      break;
+
+    case qService::IQService::GET_ACTIVE_CONFIG:
+      status = HandleGetActiveDisplayConfig(input_parcel, output_parcel);
+      break;
+
+    case qService::IQService::GET_CONFIG_COUNT:
+      status = HandleGetDisplayConfigCount(input_parcel, output_parcel);
+      break;
+
+    case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
+      status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
+      break;
+
+    case qService::IQService::GET_PANEL_BRIGHTNESS:
+      status = GetPanelBrightness(input_parcel, output_parcel);
+      break;
+
+    case qService::IQService::SET_PANEL_BRIGHTNESS:
+      status = SetPanelBrightness(input_parcel, output_parcel);
+      break;
+
+    case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
+      status = GetVisibleDisplayRect(input_parcel, output_parcel);
+      break;
+
+    case qService::IQService::SET_CAMERA_STATUS:
+      status = SetDynamicBWForCamera(input_parcel, output_parcel);
+      break;
+
+    case qService::IQService::GET_BW_TRANSACTION_STATUS:
+      status = GetBWTransactionStatus(input_parcel, output_parcel);
+      break;
+
+    case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
+      status = SetMixerResolution(input_parcel);
+      break;
+
+    case qService::IQService::SET_COLOR_MODE:
+      status = SetColorModeOverride(input_parcel);
+      break;
+
+    case qService::IQService::SET_COLOR_MODE_BY_ID:
+      status = SetColorModeById(input_parcel);
+      break;
+
+    default:
+      DLOGW("QService command = %d is not supported", command);
+      return -EINVAL;
+  }
+
+  return status;
+}
+
+android::status_t HWCSession::ToggleScreenUpdates(const android::Parcel *input_parcel,
+                                                  android::Parcel *output_parcel) {
+  int input = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+
+  if (hwc_display_[HWC_DISPLAY_PRIMARY] && (input <= 1) && (input >= 0)) {
+    error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(input == 1);
+    if (error != 0) {
+      DLOGE("Failed to toggle screen updates = %d. Error = %d", input, error);
+    }
+  }
+  output_parcel->writeInt32(error);
+
+  return error;
+}
+
+android::status_t HWCSession::SetPanelBrightness(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel) {
+  int level = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+
+  if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(level);
+    if (error != 0) {
+      DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
+    }
+  }
+  output_parcel->writeInt32(error);
+
+  return error;
+}
+
+android::status_t HWCSession::GetPanelBrightness(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel) {
+  int error = android::BAD_VALUE;
+  int ret = error;
+
+  if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(&ret);
+    if (error != 0) {
+      ret = error;
+      DLOGE("Failed to get the panel brightness. Error = %d", error);
+    }
+  }
+  output_parcel->writeInt32(ret);
+
+  return error;
+}
+
+android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel,
+                                                   android::Parcel *out) {
+  DisplayError error = kErrorNone;
+  int ret = 0;
+  uint32_t disp_id = UINT32(input_parcel->readInt32());
+  uint32_t enable = UINT32(input_parcel->readInt32());
+
+  if (disp_id != HWC_DISPLAY_PRIMARY) {
+    DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
+    ret = -EINVAL;
+    out->writeInt32(ret);
+    return ret;
+  }
+
+  if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    DLOGE("primary display object is not instantiated");
+    ret = -EINVAL;
+    out->writeInt32(ret);
+    return ret;
+  }
+
+  uint32_t pending = 0;
+  error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlPartialUpdate(enable, &pending);
+
+  if (error == kErrorNone) {
+    if (!pending) {
+      out->writeInt32(ret);
+      return ret;
+    }
+  } else if (error == kErrorNotSupported) {
+    out->writeInt32(ret);
+    return ret;
+  } else {
+    ret = -EINVAL;
+    out->writeInt32(ret);
+    return ret;
+  }
+
+  // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
+  callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+
+  // Wait until partial update control is complete
+  ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
+
+  out->writeInt32(ret);
+
+  return ret;
+}
+
+android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
+                                                           android::Parcel *output_parcel) {
+  int config = input_parcel->readInt32();
+  int dpy = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+
+  if (dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;
+  }
+
+  if (hwc_display_[dpy]) {
+    error = hwc_display_[dpy]->SetActiveDisplayConfig(config);
+    if (error == 0) {
+      callbacks_.Refresh(0);
+    }
+  }
+
+  return error;
+}
+
+android::status_t HWCSession::HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
+                                                           android::Parcel *output_parcel) {
+  int dpy = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+
+  if (dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;
+  }
+
+  if (hwc_display_[dpy]) {
+    uint32_t config = 0;
+    error = hwc_display_[dpy]->GetActiveDisplayConfig(&config);
+    if (error == 0) {
+      output_parcel->writeInt32(INT(config));
+    }
+  }
+
+  return error;
+}
+
+android::status_t HWCSession::HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
+                                                          android::Parcel *output_parcel) {
+  int dpy = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+
+  if (dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;
+  }
+
+  uint32_t count = 0;
+  if (hwc_display_[dpy]) {
+    error = hwc_display_[dpy]->GetDisplayConfigCount(&count);
+    if (error == 0) {
+      output_parcel->writeInt32(INT(count));
+    }
+  }
+
+  return error;
+}
+
+android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
+                                                                  *input_parcel,
+                                                                  android::Parcel *output_parcel) {
+  int config = input_parcel->readInt32();
+  int dpy = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+  DisplayConfigVariableInfo display_attributes;
+
+  if (dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;
+  }
+
+  if (hwc_display_[dpy]) {
+    error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
+    if (error == 0) {
+      output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
+      output_parcel->writeInt32(INT(display_attributes.x_pixels));
+      output_parcel->writeInt32(INT(display_attributes.y_pixels));
+      output_parcel->writeFloat(display_attributes.x_dpi);
+      output_parcel->writeFloat(display_attributes.y_dpi);
+      output_parcel->writeInt32(0);  // Panel type, unsupported.
+    }
+  }
+
+  return error;
+}
+
+android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
+                                                        android::Parcel *output_parcel) {
+  int ret = -EINVAL;
+
+  uint32_t display_id = UINT32(input_parcel->readInt32());
+  uint32_t display_status = UINT32(input_parcel->readInt32());
+
+  DLOGI("Display = %d, Status = %d", display_id, display_status);
+
+  if (display_id >= HWC_NUM_DISPLAY_TYPES) {
+    DLOGE("Invalid display_id");
+  } else if (display_id == HWC_DISPLAY_PRIMARY) {
+    DLOGE("Not supported for this display");
+  } else if (!hwc_display_[display_id]) {
+    DLOGW("Display is not connected");
+  } else {
+    ret = hwc_display_[display_id]->SetDisplayStatus(display_status);
+  }
+
+  output_parcel->writeInt32(ret);
+
+  return ret;
+}
+
+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:
+      return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
+          HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
+    case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
+      return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
+          HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
+    case qdutils::SET_BINDER_DYN_REFRESH_RATE: {
+      uint32_t refresh_rate = UINT32(input_parcel->readInt32());
+      return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
+          HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
+    }
+    default:
+      DLOGW("Invalid operation %d", operation);
+      return -EINVAL;
+  }
+
+  return 0;
+}
+
+android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
+  uint32_t mode = UINT32(input_parcel->readInt32());
+  return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
+}
+
+android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
+  DisplayError error = kErrorNone;
+  std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
+  uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
+
+  if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
+    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+      error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+    }
+  }
+
+  if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
+    if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+      error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+    }
+  }
+
+  if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
+    if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+      error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+    }
+  }
+
+  return 0;
+}
+
+android::status_t HWCSession::SetDynamicBWForCamera(const android::Parcel *input_parcel,
+                                                    android::Parcel *output_parcel) {
+  DisplayError error = kErrorNone;
+  uint32_t camera_status = UINT32(input_parcel->readInt32());
+  HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault;
+
+  // trigger invalidate to apply new bw caps.
+  callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+
+  error = core_intf_->SetMaxBandwidthMode(mode);
+  if (error != kErrorNone) {
+    return -EINVAL;
+  }
+
+  new_bw_mode_ = true;
+  need_invalidate_ = true;
+
+  return 0;
+}
+
+android::status_t HWCSession::GetBWTransactionStatus(const android::Parcel *input_parcel,
+                                                     android::Parcel *output_parcel) {
+  bool state = true;
+
+  if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    if (sync_wait(bw_mode_release_fd_, 0) < 0) {
+      DLOGI("bw_transaction_release_fd is not yet signalled: err= %s", strerror(errno));
+      state = false;
+    }
+    output_parcel->writeInt32(state);
+  }
+
+  return 0;
+}
+
+void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
+  uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
+  std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
+  uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
+
+  if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
+    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+      hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+
+  if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
+    if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+      hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+
+  if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
+    if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+      hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+}
+
+android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
+  DisplayError error = kErrorNone;
+  uint32_t dpy = UINT32(input_parcel->readInt32());
+
+  if (dpy != HWC_DISPLAY_PRIMARY) {
+    DLOGI("Resoulution change not supported for this display %d", dpy);
+    return -EINVAL;
+  }
+
+  if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    DLOGI("Primary display is not initialized");
+    return -EINVAL;
+  }
+
+  uint32_t width = UINT32(input_parcel->readInt32());
+  uint32_t height = UINT32(input_parcel->readInt32());
+
+  error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
+  if (error != kErrorNone) {
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
+android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) {
+  auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
+  auto mode = static_cast<android_color_mode_t>(input_parcel->readInt32());
+  auto device = static_cast<hwc2_device_t *>(this);
+  auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
+  if (err != HWC2_ERROR_NONE)
+    return -EINVAL;
+  return 0;
+}
+
+android::status_t HWCSession::SetColorModeById(const android::Parcel *input_parcel) {
+  auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
+  auto mode = input_parcel->readInt32();
+  auto device = static_cast<hwc2_device_t *>(this);
+  auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorModeById, mode);
+  if (err != HWC2_ERROR_NONE)
+    return -EINVAL;
+  return 0;
+}
+
+void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
+  int type = input_parcel->readInt32();
+  bool enable = (input_parcel->readInt32() > 0);
+  DLOGI("type = %d enable = %d", type, enable);
+  int verbose_level = input_parcel->readInt32();
+
+  switch (type) {
+    case qService::IQService::DEBUG_ALL:
+      HWCDebugHandler::DebugAll(enable, verbose_level);
+      break;
+
+    case qService::IQService::DEBUG_MDPCOMP:
+      HWCDebugHandler::DebugStrategy(enable, verbose_level);
+      HWCDebugHandler::DebugCompManager(enable, verbose_level);
+      break;
+
+    case qService::IQService::DEBUG_PIPE_LIFECYCLE:
+      HWCDebugHandler::DebugResources(enable, verbose_level);
+      break;
+
+    case qService::IQService::DEBUG_DRIVER_CONFIG:
+      HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
+      break;
+
+    case qService::IQService::DEBUG_ROTATOR:
+      HWCDebugHandler::DebugResources(enable, verbose_level);
+      HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
+      HWCDebugHandler::DebugRotator(enable, verbose_level);
+      break;
+
+    case qService::IQService::DEBUG_QDCM:
+      HWCDebugHandler::DebugQdcm(enable, verbose_level);
+      break;
+
+    default:
+      DLOGW("type = %d is not supported", type);
+  }
+}
+
+android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
+                                             android::Parcel *output_parcel) {
+  int ret = 0;
+  int32_t *brightness_value = NULL;
+  uint32_t display_id(0);
+  PPPendingParams pending_action;
+  PPDisplayAPIPayload resp_payload, req_payload;
+
+  if (!color_mgr_) {
+    return -1;
+  }
+
+  pending_action.action = kNoAction;
+  pending_action.params = NULL;
+
+  // Read display_id, payload_size and payload from in_parcel.
+  ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
+  if (!ret) {
+    if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY])
+      ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload, &resp_payload,
+                                                                    &pending_action);
+
+    if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL])
+      ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload,
+                                                                     &pending_action);
+  }
+
+  if (ret) {
+    output_parcel->writeInt32(ret);  // first field in out parcel indicates return code.
+    req_payload.DestroyPayload();
+    resp_payload.DestroyPayload();
+    return ret;
+  }
+
+  switch (pending_action.action) {
+    case kInvalidating:
+      callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+      break;
+    case kEnterQDCMMode:
+      ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+      break;
+    case kExitQDCMMode:
+      ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+      break;
+    case kApplySolidFill:
+      ret =
+          color_mgr_->SetSolidFill(pending_action.params, true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+      callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+      break;
+    case kDisableSolidFill:
+      ret =
+          color_mgr_->SetSolidFill(pending_action.params, false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+      callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+      break;
+    case kSetPanelBrightness:
+      brightness_value = reinterpret_cast<int32_t *>(resp_payload.payload);
+      if (brightness_value == NULL) {
+        DLOGE("Brightness value is Null");
+        return -EINVAL;
+      }
+      if (HWC_DISPLAY_PRIMARY == display_id)
+        ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
+      break;
+    case kEnableFrameCapture:
+      ret = color_mgr_->SetFrameCapture(pending_action.params, true,
+                                        hwc_display_[HWC_DISPLAY_PRIMARY]);
+      callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+      break;
+    case kDisableFrameCapture:
+      ret = color_mgr_->SetFrameCapture(pending_action.params, false,
+                                        hwc_display_[HWC_DISPLAY_PRIMARY]);
+      break;
+    case kConfigureDetailedEnhancer:
+      ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
+                                            hwc_display_[HWC_DISPLAY_PRIMARY]);
+      callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+      break;
+    case kNoAction:
+      break;
+    default:
+      DLOGW("Invalid pending action = %d!", pending_action.action);
+      break;
+  }
+
+  // for display API getter case, marshall returned params into out_parcel.
+  output_parcel->writeInt32(ret);
+  HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
+  req_payload.DestroyPayload();
+  resp_payload.DestroyPayload();
+
+  return (ret ? -EINVAL : 0);
+}
+
+android::status_t HWCSession::OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
+                                                             android::Parcel *output_parcel) {
+  int ret = -EINVAL;
+  uint32_t display_id = UINT32(input_parcel->readInt32());
+  uint32_t min_enc_level = UINT32(input_parcel->readInt32());
+
+  DLOGI("Display %d", display_id);
+
+  if (display_id >= HWC_NUM_DISPLAY_TYPES) {
+    DLOGE("Invalid display_id");
+  } else if (display_id != HWC_DISPLAY_EXTERNAL) {
+    DLOGE("Not supported for display");
+  } else if (!hwc_display_[display_id]) {
+    DLOGW("Display is not connected");
+  } else {
+    ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange(min_enc_level);
+  }
+
+  output_parcel->writeInt32(ret);
+
+  return ret;
+}
+
+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) {
+        callbacks_.Refresh(0);
+        reset_panel_ = true;
+      }
+    }
+  }
+  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)) {
+    const 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() {
+  HWC2::Error status;
+
+  DLOGI("Powering off primary");
+  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC2::PowerMode::Off);
+  if (status != HWC2::Error::None) {
+    DLOGE("power-off on primary failed with error = %d", status);
+  }
+
+  DLOGI("Restoring power mode on primary");
+  HWC2::PowerMode mode = hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode();
+  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode);
+  if (status != HWC2::Error::None) {
+    DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
+  }
+
+  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetVsyncEnabled(HWC2::Vsync::Enable);
+  if (status != HWC2::Error::None) {
+    DLOGE("enabling vsync failed for primary with error = %d", status);
+  }
+
+  reset_panel_ = false;
+}
+
+int HWCSession::HotPlugHandler(bool connected) {
+  int status = 0;
+  bool notify_hotplug = false;
+  bool hdmi_primary = false;
+
+  // To prevent sending events to client while a lock is held, acquire scope locks only within
+  // below scope so that those get automatically unlocked after the scope ends.
+  {
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+    if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+      DLOGE("Primary display is not connected.");
+      return -1;
+    }
+
+    HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
+    HWCDisplay *external_display = NULL;
+
+    if (primary_display->GetDisplayClass() == DISPLAY_CLASS_EXTERNAL) {
+      external_display = static_cast<HWCDisplayExternal *>(hwc_display_[HWC_DISPLAY_PRIMARY]);
+      hdmi_primary = true;
+    }
+
+    // If primary display connected is a NULL display, then replace it with the external display
+    if (connected) {
+      // If we are in HDMI as primary and the primary display just got plugged in
+      if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+        DLOGE("HDMI is already connected");
+        return -1;
+      }
+
+      // Connect external display if virtual display is not connected.
+      // Else, defer external display connection and process it when virtual display
+      // tears down; Do not notify SurfaceFlinger since connection is deferred now.
+      if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+        status = ConnectDisplay(HWC_DISPLAY_EXTERNAL);
+        if (status) {
+          return status;
+        }
+        notify_hotplug = true;
+      } else {
+        DLOGI("Virtual display is connected, pending connection");
+        external_pending_connect_ = true;
+      }
+    } else {
+      // Do not return error if external display is not in connected status.
+      // Due to virtual display concurrency, external display connection might be still pending
+      // but hdmi got disconnected before pending connection could be processed.
+
+      if (hdmi_primary) {
+        assert(external_display != NULL);
+        uint32_t x_res, y_res;
+        external_display->GetFrameBufferResolution(&x_res, &y_res);
+        // Need to manually disable VSYNC as SF is not aware of connect/disconnect cases
+        // for HDMI as primary
+        external_display->SetVsyncEnabled(HWC2::Vsync::Disable);
+        HWCDisplayExternal::Destroy(external_display);
+
+        // In HWC2, primary displays can be hotplugged out
+        notify_hotplug = true;
+      } else {
+        if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+          status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
+          notify_hotplug = true;
+        }
+        external_pending_connect_ = false;
+      }
+    }
+  }
+
+  if (connected && notify_hotplug) {
+    // trigger screen refresh to ensure sufficient resources are available to process new
+    // new display connection.
+    callbacks_.Refresh(0);
+    uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
+    usleep(vsync_period * 2 / 1000);
+  }
+  // notify client
+  // Handle HDMI as primary here
+  if (notify_hotplug) {
+    callbacks_.Hotplug(HWC_DISPLAY_EXTERNAL,
+                       connected ? HWC2::Connection::Connected : HWC2::Connection::Disconnected);
+  }
+
+  qservice_->onHdmiHotplug(INT(connected));
+
+  return 0;
+}
+
+int HWCSession::GetVsyncPeriod(int disp) {
+  SCOPE_LOCK(locker_);
+  // default value
+  int32_t vsync_period = 1000000000l / 60;
+  auto attribute = HWC2::Attribute::VsyncPeriod;
+
+  if (hwc_display_[disp]) {
+    hwc_display_[disp]->GetDisplayAttribute(0, attribute, &vsync_period);
+  }
+
+  return vsync_period;
+}
+
+android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
+                                                    android::Parcel *output_parcel) {
+  int dpy = input_parcel->readInt32();
+
+  if (dpy < HWC_DISPLAY_PRIMARY || dpy > HWC_DISPLAY_VIRTUAL) {
+    return android::BAD_VALUE;
+  }
+
+  if (!hwc_display_[dpy]) {
+    return android::NO_INIT;
+  }
+
+  hwc_rect_t visible_rect = {0, 0, 0, 0};
+  int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
+  if (error < 0) {
+    return error;
+  }
+
+  output_parcel->writeInt32(visible_rect.left);
+  output_parcel->writeInt32(visible_rect.top);
+  output_parcel->writeInt32(visible_rect.right);
+  output_parcel->writeInt32(visible_rect.bottom);
+
+  return android::NO_ERROR;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc2/hwc_session.h b/sdm845/sdm/libs/hwc2/hwc_session.h
new file mode 100644
index 0000000..7d31a3a
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_session.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HWC_SESSION_H__
+#define __HWC_SESSION_H__
+
+#include <core/core_interface.h>
+#include <utils/locker.h>
+
+#include "hwc_callbacks.h"
+#include "hwc_layers.h"
+#include "hwc_display.h"
+#include "hwc_display_primary.h"
+#include "hwc_display_external.h"
+#include "hwc_display_virtual.h"
+#include "hwc_color_manager.h"
+#include "hwc_socket_handler.h"
+
+namespace sdm {
+
+class HWCSession : hwc2_device_t, 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();
+  HWC2::Error CreateVirtualDisplayObject(uint32_t width, uint32_t height, int32_t *format);
+
+  template <typename... Args>
+  static int32_t CallDisplayFunction(hwc2_device_t *device, hwc2_display_t display,
+                                     HWC2::Error (HWCDisplay::*member)(Args...), Args... args) {
+    if (!device) {
+      return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    HWCSession *hwc_session = static_cast<HWCSession *>(device);
+    auto status = HWC2::Error::BadDisplay;
+    if (hwc_session->hwc_display_[display]) {
+      auto hwc_display = hwc_session->hwc_display_[display];
+      status = (hwc_display->*member)(std::forward<Args>(args)...);
+    }
+    return INT32(status);
+  }
+
+  template <typename... Args>
+  static int32_t CallLayerFunction(hwc2_device_t *device, hwc2_display_t display,
+                                   hwc2_layer_t layer, HWC2::Error (HWCLayer::*member)(Args...),
+                                   Args... args) {
+    if (!device) {
+      return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    HWCSession *hwc_session = static_cast<HWCSession *>(device);
+    int32_t status = INT32(HWC2::Error::BadDisplay);
+    if (hwc_session->hwc_display_[display]) {
+      status = hwc_session->hwc_display_[display]->CallLayerFunction(layer, member, args...);
+    }
+    return status;
+  }
+
+  // HWC2 Functions that require a concrete implementation in hwc session
+  // and hence need to be member functions
+  static int32_t AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display);
+  static int32_t CreateLayer(hwc2_device_t *device, hwc2_display_t display,
+                             hwc2_layer_t *out_layer_id);
+  static int32_t CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height,
+                                      int32_t *format, hwc2_display_t *out_display_id);
+  static int32_t DestroyLayer(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer);
+  static int32_t DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display);
+  static void Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer);
+  static int32_t PresentDisplay(hwc2_device_t *device, hwc2_display_t display,
+                                int32_t *out_retire_fence);
+  static int32_t RegisterCallback(hwc2_device_t *device, int32_t descriptor,
+                                  hwc2_callback_data_t callback_data,
+                                  hwc2_function_pointer_t pointer);
+  static int32_t SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display,
+                                 buffer_handle_t buffer, int32_t releaseFence);
+  static int32_t SetLayerZOrder(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
+                                uint32_t z);
+  static int32_t SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode);
+  static int32_t ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
+                                 uint32_t *out_num_types, uint32_t *out_num_requests);
+  static int32_t SetColorMode(hwc2_device_t *device, hwc2_display_t display,
+                              int32_t /*android_color_mode_t*/ int_mode);
+  static int32_t SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
+                                   const float *matrix, int32_t /*android_color_transform_t*/ hint);
+
+ private:
+  static const int kExternalConnectionTimeoutMs = 500;
+  static const int kPartialUpdateControlTimeoutMs = 100;
+
+  // 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 void GetCapabilities(struct hwc2_device *device, uint32_t *outCount,
+                              int32_t *outCapabilities);
+  static hwc2_function_pointer_t GetFunction(struct hwc2_device *device, int32_t descriptor);
+
+  // 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();
+  int32_t ConnectDisplay(int disp);
+  int DisconnectDisplay(int disp);
+  int GetVsyncPeriod(int disp);
+
+  // 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,
+                                              android::Parcel *output_parcel);
+  android::status_t ToggleScreenUpdates(const android::Parcel *input_parcel,
+                                        android::Parcel *output_parcel);
+  android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
+  android::status_t QdcmCMDHandler(const android::Parcel *input_parcel,
+                                   android::Parcel *output_parcel);
+  android::status_t ControlPartialUpdate(const android::Parcel *input_parcel, android::Parcel *out);
+  android::status_t OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
+                                                   android::Parcel *output_parcel);
+  android::status_t SetPanelBrightness(const android::Parcel *input_parcel,
+                                       android::Parcel *output_parcel);
+  android::status_t GetPanelBrightness(const android::Parcel *input_parcel,
+                                       android::Parcel *output_parcel);
+  // These functions return the actual display config info as opposed to FB
+  android::status_t HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel);
+  android::status_t HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel);
+  android::status_t HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
+                                                android::Parcel *output_parcel);
+  android::status_t HandleGetDisplayAttributesForConfig(const android::Parcel *input_parcel,
+                                                        android::Parcel *output_parcel);
+  android::status_t GetVisibleDisplayRect(const android::Parcel *input_parcel,
+                                          android::Parcel *output_parcel);
+
+  android::status_t SetDynamicBWForCamera(const android::Parcel *input_parcel,
+                                          android::Parcel *output_parcel);
+  android::status_t GetBWTransactionStatus(const android::Parcel *input_parcel,
+                                           android::Parcel *output_parcel);
+  android::status_t SetMixerResolution(const android::Parcel *input_parcel);
+
+  android::status_t SetColorModeOverride(const android::Parcel *input_parcel);
+
+  android::status_t SetColorModeById(const android::Parcel *input_parcel);
+
+  static Locker locker_;
+  CoreInterface *core_intf_ = NULL;
+  HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {NULL};
+  HWCCallbacks callbacks_;
+  pthread_t uevent_thread_;
+  bool uevent_thread_exit_ = false;
+  const char *uevent_thread_name_ = "HWC_UeventThread";
+  HWCBufferAllocator *buffer_allocator_;
+  HWCBufferSyncHandler buffer_sync_handler_;
+  HWCColorManager *color_mgr_ = NULL;
+  bool reset_panel_ = false;
+  bool secure_display_active_ = false;
+  bool external_pending_connect_ = false;
+  bool new_bw_mode_ = false;
+  bool need_invalidate_ = false;
+  int bw_mode_release_fd_ = -1;
+  qService::QService *qservice_ = NULL;
+  HWCSocketHandler socket_handler_;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_SESSION_H__
diff --git a/sdm845/sdm/libs/hwc2/hwc_tonemapper.cpp b/sdm845/sdm/libs/hwc2/hwc_tonemapper.cpp
new file mode 100644
index 0000000..7bda725
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_tonemapper.cpp
@@ -0,0 +1,341 @@
+/*
+* Copyright (c) 2016 - 2017, 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 <sync/sync.h>
+
+#include <TonemapFactory.h>
+
+#include <core/buffer_allocator.h>
+
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/formats.h>
+#include <utils/rect.h>
+#include <utils/utils.h>
+
+#include <vector>
+
+#include "hwc_debugger.h"
+#include "hwc_tonemapper.h"
+
+#define __CLASS__ "HWCToneMapper"
+
+namespace sdm {
+
+ToneMapSession::ToneMapSession(HWCBufferAllocator *buffer_allocator) :
+                buffer_allocator_(buffer_allocator) {
+  buffer_info_.resize(kNumIntermediateBuffers);
+}
+
+ToneMapSession::~ToneMapSession() {
+  delete gpu_tone_mapper_;
+  gpu_tone_mapper_ = nullptr;
+  FreeIntermediateBuffers();
+  buffer_info_.clear();
+}
+
+DisplayError ToneMapSession::AllocateIntermediateBuffers(const Layer *layer) {
+  DisplayError error = kErrorNone;
+  for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
+    BufferInfo &buffer_info = buffer_info_[i];
+    buffer_info.buffer_config.width = layer->request.width;
+    buffer_info.buffer_config.height = layer->request.height;
+    buffer_info.buffer_config.format = layer->request.format;
+    buffer_info.buffer_config.secure = layer->request.flags.secure;
+    buffer_info.buffer_config.gfx_client = true;
+    error = buffer_allocator_->AllocateBuffer(&buffer_info);
+    if (error != kErrorNone) {
+      FreeIntermediateBuffers();
+      return error;
+    }
+  }
+
+  return kErrorNone;
+}
+
+void ToneMapSession::FreeIntermediateBuffers() {
+  for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
+    // Free the valid fence
+    if (release_fence_fd_[i] >= 0) {
+      CloseFd(&release_fence_fd_[i]);
+    }
+    BufferInfo &buffer_info = buffer_info_[i];
+    if (buffer_info.private_data) {
+      buffer_allocator_->FreeBuffer(&buffer_info);
+    }
+  }
+}
+
+void ToneMapSession::UpdateBuffer(int acquire_fence, LayerBuffer *buffer) {
+  // Acquire fence will be closed by HWC Display.
+  // Fence returned by GPU will be closed in PostCommit.
+  buffer->acquire_fence_fd = acquire_fence;
+  buffer->size = buffer_info_[current_buffer_index_].alloc_buffer_info.size;
+  buffer->planes[0].fd = buffer_info_[current_buffer_index_].alloc_buffer_info.fd;
+}
+
+void ToneMapSession::SetReleaseFence(int fd) {
+  CloseFd(&release_fence_fd_[current_buffer_index_]);
+  // Used to give to GPU tonemapper along with input layer fd
+  release_fence_fd_[current_buffer_index_] = dup(fd);
+}
+
+void ToneMapSession::SetToneMapConfig(Layer *layer) {
+  // HDR -> SDR is FORWARD and SDR - > HDR is INVERSE
+  tone_map_config_.type = layer->input_buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
+  tone_map_config_.colorPrimaries = layer->input_buffer.color_metadata.colorPrimaries;
+  tone_map_config_.transfer = layer->input_buffer.color_metadata.transfer;
+  tone_map_config_.secure = layer->request.flags.secure;
+  tone_map_config_.format = layer->request.format;
+}
+
+bool ToneMapSession::IsSameToneMapConfig(Layer *layer) {
+  LayerBuffer& buffer = layer->input_buffer;
+  private_handle_t *handle = static_cast<private_handle_t *>(buffer_info_[0].private_data);
+  int tonemap_type = buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
+
+  return ((tonemap_type == tone_map_config_.type) &&
+          (buffer.color_metadata.colorPrimaries == tone_map_config_.colorPrimaries) &&
+          (buffer.color_metadata.transfer == tone_map_config_.transfer) &&
+          (layer->request.flags.secure == tone_map_config_.secure) &&
+          (layer->request.format == tone_map_config_.format) &&
+          (layer->request.width == UINT32(handle->unaligned_width)) &&
+          (layer->request.height == UINT32(handle->unaligned_height)));
+}
+
+int HWCToneMapper::HandleToneMap(LayerStack *layer_stack) {
+  uint32_t gpu_count = 0;
+  DisplayError error = kErrorNone;
+
+  for (uint32_t i = 0; i < layer_stack->layers.size(); i++) {
+    uint32_t session_index = 0;
+    Layer *layer = layer_stack->layers.at(i);
+    if (layer->composition == kCompositionGPU) {
+      gpu_count++;
+    }
+
+    if (layer->request.flags.tone_map) {
+      switch (layer->composition) {
+      case kCompositionGPUTarget:
+        if (!gpu_count) {
+          // When all layers are on FrameBuffer and if they do not update in the next draw cycle,
+          // then SDM marks them for SDE Composition because the cached FB layer gets displayed.
+          // GPU count will be 0 in this case. Try to use the existing tone-mapped frame buffer.
+          // No ToneMap/Blit is required. Just update the buffer & acquire fence fd of FB layer.
+          if (!tone_map_sessions_.empty()) {
+            ToneMapSession *fb_tone_map_session = tone_map_sessions_.at(fb_session_index_);
+            fb_tone_map_session->UpdateBuffer(-1 /* acquire_fence */, &layer->input_buffer);
+            fb_tone_map_session->layer_index_ = INT(i);
+            fb_tone_map_session->acquired_ = true;
+            return 0;
+          }
+        }
+        error = AcquireToneMapSession(layer, &session_index);
+        fb_session_index_ = session_index;
+        break;
+      default:
+        error = AcquireToneMapSession(layer, &session_index);
+        break;
+      }
+
+      if (error != kErrorNone) {
+        Terminate();
+        return -1;
+      }
+
+      ToneMapSession *session = tone_map_sessions_.at(session_index);
+      ToneMap(layer, session);
+      session->layer_index_ = INT(i);
+    }
+  }
+
+  return 0;
+}
+
+void HWCToneMapper::ToneMap(Layer* layer, ToneMapSession *session) {
+  int fence_fd = -1;
+  int acquire_fd = -1;
+  int merged_fd = -1;
+
+  uint8_t buffer_index = session->current_buffer_index_;
+  const private_handle_t *dst_hnd = static_cast<private_handle_t *>
+                                    (session->buffer_info_[buffer_index].private_data);
+  const private_handle_t *src_hnd = reinterpret_cast<const private_handle_t *>
+                                    (layer->input_buffer.buffer_id);
+
+  // use and close the layer->input_buffer acquire fence fd.
+  acquire_fd = layer->input_buffer.acquire_fence_fd;
+  buffer_sync_handler_.SyncMerge(session->release_fence_fd_[buffer_index], acquire_fd, &merged_fd);
+
+  if (acquire_fd >= 0) {
+    CloseFd(&acquire_fd);
+  }
+
+  if (session->release_fence_fd_[buffer_index] >= 0) {
+    CloseFd(&session->release_fence_fd_[buffer_index]);
+  }
+
+  DTRACE_BEGIN("GPU_TM_BLIT");
+  fence_fd = session->gpu_tone_mapper_->blit(reinterpret_cast<const void *>(dst_hnd),
+                                             reinterpret_cast<const void *>(src_hnd), merged_fd);
+  DTRACE_END();
+
+  DumpToneMapOutput(session, &fence_fd);
+  session->UpdateBuffer(fence_fd, &layer->input_buffer);
+}
+
+void HWCToneMapper::PostCommit(LayerStack *layer_stack) {
+  auto it = tone_map_sessions_.begin();
+  while (it != tone_map_sessions_.end()) {
+    uint32_t session_index = UINT32(std::distance(tone_map_sessions_.begin(), it));
+    ToneMapSession *session = tone_map_sessions_.at(session_index);
+    if (session->acquired_) {
+      Layer *layer = layer_stack->layers.at(UINT32(session->layer_index_));
+      // Close the fd returned by GPU ToneMapper and set release fence.
+      LayerBuffer &layer_buffer = layer->input_buffer;
+      CloseFd(&layer_buffer.acquire_fence_fd);
+      session->SetReleaseFence(layer_buffer.release_fence_fd);
+      session->acquired_ = false;
+      it++;
+    } else {
+      delete session;
+      it = tone_map_sessions_.erase(it);
+    }
+  }
+}
+
+void HWCToneMapper::Terminate() {
+  if (tone_map_sessions_.size()) {
+    while (!tone_map_sessions_.empty()) {
+      delete tone_map_sessions_.back();
+      tone_map_sessions_.pop_back();
+    }
+    fb_session_index_ = 0;
+  }
+}
+
+void HWCToneMapper::SetFrameDumpConfig(uint32_t count) {
+  DLOGI("Dump FrameConfig count = %d", count);
+  dump_frame_count_ = count;
+  dump_frame_index_ = 0;
+}
+
+void HWCToneMapper::DumpToneMapOutput(ToneMapSession *session, int *acquire_fd) {
+  if (!dump_frame_count_) {
+    return;
+  }
+
+  BufferInfo &buffer_info = session->buffer_info_[session->current_buffer_index_];
+  private_handle_t *target_buffer = static_cast<private_handle_t *>(buffer_info.private_data);
+
+  if (*acquire_fd >= 0) {
+    int error = sync_wait(*acquire_fd, 1000);
+    if (error < 0) {
+      DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+      return;
+    }
+  }
+
+  size_t result = 0;
+  char dump_file_name[PATH_MAX];
+  snprintf(dump_file_name, sizeof(dump_file_name), "/data/misc/display/frame_dump_primary"
+           "/tonemap_%dx%d_frame%d.raw", target_buffer->width, target_buffer->height,
+           dump_frame_index_);
+
+  FILE* fp = fopen(dump_file_name, "w+");
+  if (fp) {
+    DLOGI("base addr = %x", target_buffer->base);
+    result = fwrite(reinterpret_cast<void *>(target_buffer->base), target_buffer->size, 1, fp);
+    fclose(fp);
+  }
+  dump_frame_count_--;
+  dump_frame_index_++;
+  CloseFd(acquire_fd);
+}
+
+DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index) {
+  Color10Bit *grid_entries = NULL;
+  int grid_size = 0;
+
+  if (layer->lut_3d.validGridEntries) {
+    grid_entries = layer->lut_3d.gridEntries;
+    grid_size = INT(layer->lut_3d.gridSize);
+  }
+
+  // When the property sdm.disable_hdr_lut_gen is set, the lutEntries and gridEntries in
+  // the Lut3d will be NULL, clients needs to allocate the memory and set correct 3D Lut
+  // for Tonemapping.
+  if (!layer->lut_3d.lutEntries || !layer->lut_3d.dim) {
+    // Atleast lutEntries must be valid for GPU Tonemapper.
+    DLOGE("Invalid Lut Entries or lut dimension = %d", layer->lut_3d.dim);
+    return kErrorParameters;
+  }
+
+  // Check if we can re-use an existing tone map session.
+  for (uint32_t i = 0; i < tone_map_sessions_.size(); i++) {
+    ToneMapSession *tonemap_session = tone_map_sessions_.at(i);
+    if (!tonemap_session->acquired_ && tonemap_session->IsSameToneMapConfig(layer)) {
+      tonemap_session->current_buffer_index_ = (tonemap_session->current_buffer_index_ + 1) %
+                                                ToneMapSession::kNumIntermediateBuffers;
+      tonemap_session->acquired_ = true;
+      *session_index = i;
+      return kErrorNone;
+    }
+  }
+
+  ToneMapSession *session = new ToneMapSession(buffer_allocator_);
+
+  session->SetToneMapConfig(layer);
+  session->gpu_tone_mapper_ = TonemapperFactory_GetInstance(session->tone_map_config_.type,
+                                                            layer->lut_3d.lutEntries,
+                                                            layer->lut_3d.dim,
+                                                            grid_entries, grid_size,
+                                                            session->tone_map_config_.secure);
+
+  if (session->gpu_tone_mapper_ == NULL) {
+    DLOGE("Get Tonemapper failed!");
+    delete session;
+    return kErrorNotSupported;
+  }
+  DisplayError error = session->AllocateIntermediateBuffers(layer);
+  if (error != kErrorNone) {
+    DLOGE("Allocation of Intermediate Buffers failed!");
+    delete session;
+    return error;
+  }
+
+  session->acquired_ = true;
+  tone_map_sessions_.push_back(session);
+  *session_index = UINT32(tone_map_sessions_.size() - 1);
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
diff --git a/sdm845/sdm/libs/hwc2/hwc_tonemapper.h b/sdm845/sdm/libs/hwc2/hwc_tonemapper.h
new file mode 100644
index 0000000..8367c3e
--- /dev/null
+++ b/sdm845/sdm/libs/hwc2/hwc_tonemapper.h
@@ -0,0 +1,103 @@
+/*
+* Copyright (c) 2016 - 2017, 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_TONEMAPPER_H__
+#define __HWC_TONEMAPPER_H__
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include <hardware/hwcomposer.h>
+
+#include <core/layer_stack.h>
+#include <utils/sys.h>
+#include <vector>
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_buffer_allocator.h"
+
+class Tonemapper;
+
+namespace sdm {
+
+struct ToneMapConfig {
+  int type = 0;
+  ColorPrimaries colorPrimaries = ColorPrimaries_Max;
+  GammaTransfer transfer = Transfer_Max;
+  LayerBufferFormat format = kFormatRGBA8888;
+  bool secure = false;
+};
+
+class ToneMapSession {
+ public:
+  explicit ToneMapSession(HWCBufferAllocator *buffer_allocator);
+  ~ToneMapSession();
+  DisplayError AllocateIntermediateBuffers(const Layer *layer);
+  void FreeIntermediateBuffers();
+  void UpdateBuffer(int acquire_fence, LayerBuffer *buffer);
+  void SetReleaseFence(int fd);
+  void SetToneMapConfig(Layer *layer);
+  bool IsSameToneMapConfig(Layer *layer);
+
+  static const uint8_t kNumIntermediateBuffers = 2;
+  Tonemapper *gpu_tone_mapper_ = nullptr;
+  HWCBufferAllocator *buffer_allocator_ = nullptr;
+  ToneMapConfig tone_map_config_ = {};
+  uint8_t current_buffer_index_ = 0;
+  std::vector<BufferInfo> buffer_info_ = {};
+  int release_fence_fd_[kNumIntermediateBuffers] = {-1, -1};
+  bool acquired_ = false;
+  int layer_index_ = -1;
+};
+
+class HWCToneMapper {
+ public:
+  explicit HWCToneMapper(HWCBufferAllocator *allocator) : buffer_allocator_(allocator) {}
+  ~HWCToneMapper() {}
+
+  int HandleToneMap(LayerStack *layer_stack);
+  bool IsActive() { return !tone_map_sessions_.empty(); }
+  void PostCommit(LayerStack *layer_stack);
+  void SetFrameDumpConfig(uint32_t count);
+  void Terminate();
+
+ private:
+  void ToneMap(Layer *layer, ToneMapSession *session);
+  DisplayError AcquireToneMapSession(Layer *layer, uint32_t *session_index);
+  void DumpToneMapOutput(ToneMapSession *session, int *acquire_fence);
+
+  std::vector<ToneMapSession*> tone_map_sessions_;
+  HWCBufferSyncHandler buffer_sync_handler_ = {};
+  HWCBufferAllocator *buffer_allocator_ = nullptr;
+  uint32_t dump_frame_count_ = 0;
+  uint32_t dump_frame_index_ = 0;
+  uint32_t fb_session_index_ = 0;
+};
+
+}  // namespace sdm
+#endif  // __HWC_TONEMAPPER_H__
diff --git a/sdm845/sdm/libs/utils/Android.mk b/sdm845/sdm/libs/utils/Android.mk
new file mode 100644
index 0000000..fe89104
--- /dev/null
+++ b/sdm845/sdm/libs/utils/Android.mk
@@ -0,0 +1,31 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/../../../common.mk
+
+LOCAL_MODULE                  := libsdmutils
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes)
+LOCAL_HEADER_LIBRARIES        := display_headers
+LOCAL_CFLAGS                  := -DLOG_TAG=\"SDM\" $(common_flags)
+LOCAL_SRC_FILES               := debug.cpp \
+                                 rect.cpp \
+                                 sys.cpp \
+                                 formats.cpp \
+                                 utils.cpp
+
+include $(BUILD_SHARED_LIBRARY)
+
+SDM_HEADER_PATH := ../../include
+include $(CLEAR_VARS)
+LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)/sdm/utils
+LOCAL_COPY_HEADERS             = $(SDM_HEADER_PATH)/utils/constants.h \
+                                 $(SDM_HEADER_PATH)/utils/debug.h \
+                                 $(SDM_HEADER_PATH)/utils/formats.h \
+                                 $(SDM_HEADER_PATH)/utils/locker.h \
+                                 $(SDM_HEADER_PATH)/utils/rect.h \
+                                 $(SDM_HEADER_PATH)/utils/sys.h \
+                                 $(SDM_HEADER_PATH)/utils/utils.h \
+                                 $(SDM_HEADER_PATH)/utils/factory.h
+
+include $(BUILD_COPY_HEADERS)
diff --git a/sdm845/sdm/libs/utils/Makefile.am b/sdm845/sdm/libs/utils/Makefile.am
new file mode 100644
index 0000000..d8d8dc5
--- /dev/null
+++ b/sdm845/sdm/libs/utils/Makefile.am
@@ -0,0 +1,12 @@
+cpp_sources = debug.cpp \
+              rect.cpp \
+              sys.cpp \
+              formats.cpp \
+              utils.cpp
+
+lib_LTLIBRARIES = libsdmutils.la
+libsdmutils_la_CC = @CC@
+libsdmutils_la_SOURCES = $(cpp_sources)
+libsdmutils_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"SDM\"
+libsdmutils_la_CPPFLAGS = $(AM_CPPFLAGS)
+libsdmutils_la_LDFLAGS = -shared -avoid-version
diff --git a/sdm845/sdm/libs/utils/debug.cpp b/sdm845/sdm/libs/utils/debug.cpp
new file mode 100644
index 0000000..95b4e3b
--- /dev/null
+++ b/sdm845/sdm/libs/utils/debug.cpp
@@ -0,0 +1,217 @@
+/*
+* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdlib.h>
+#include <utils/debug.h>
+#include <utils/constants.h>
+#include <string>
+#include <algorithm>
+
+namespace sdm {
+
+Debug Debug::debug_;
+
+Debug::Debug() : debug_handler_(&default_debug_handler_) {
+}
+
+int Debug::GetSimulationFlag() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sdm.composition_simulation", &value);
+
+  return value;
+}
+
+int Debug::GetHDMIResolution() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("hw.hdmi.resolution", &value);
+
+  return value;
+}
+
+void Debug::GetIdleTimeoutMs(uint32_t *active_ms, uint32_t *inactive_ms) {
+  int active_val = IDLE_TIMEOUT_ACTIVE_MS;
+  int inactive_val = IDLE_TIMEOUT_INACTIVE_MS;
+
+  debug_.debug_handler_->GetProperty("sdm.idle_time", &active_val);
+  debug_.debug_handler_->GetProperty("sdm.idle_time.inactive", &inactive_val);
+
+  *active_ms = UINT32(active_val);
+  *inactive_ms = UINT32(inactive_val);
+}
+
+int Debug::GetBootAnimLayerCount() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sdm.boot_anim_layer_count", &value);
+
+  return value;
+}
+
+bool Debug::IsRotatorDownScaleDisabled() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sdm.debug.rotator_downscale", &value);
+
+  return (value == 1);
+}
+
+bool Debug::IsDecimationDisabled() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sdm.disable_decimation", &value);
+
+  return (value == 1);
+}
+
+int Debug::GetMaxPipesPerMixer(DisplayType display_type) {
+  int value = -1;
+  switch (display_type) {
+  case kPrimary:
+    debug_.debug_handler_->GetProperty("sdm.primary.mixer_stages", &value);
+    break;
+  case kHDMI:
+    debug_.debug_handler_->GetProperty("sdm.external.mixer_stages", &value);
+    break;
+  case kVirtual:
+    debug_.debug_handler_->GetProperty("sdm.virtual.mixer_stages", &value);
+    break;
+  default:
+    break;
+  }
+
+  return value;
+}
+
+int Debug::GetMaxUpscale() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sdm.max_upscale", &value);
+
+  return value;
+}
+
+bool Debug::IsVideoModeEnabled() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sdm.video_mode_panel", &value);
+
+  return (value == 1);
+}
+
+bool Debug::IsRotatorUbwcDisabled() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sdm.debug.rotator_disable_ubwc", &value);
+
+  return (value == 1);
+}
+
+bool Debug::IsRotatorSplitDisabled() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sdm.debug.disable_rotator_split", &value);
+
+  return (value == 1);
+}
+
+bool Debug::IsScalarDisabled() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sdm.debug.disable_scalar", &value);
+
+  return (value == 1);
+}
+
+bool Debug::IsUbwcTiledFrameBuffer() {
+  int ubwc_disabled = 0;
+  int ubwc_framebuffer = 0;
+
+  debug_.debug_handler_->GetProperty("debug.gralloc.gfx_ubwc_disable", &ubwc_disabled);
+
+  if (!ubwc_disabled) {
+    debug_.debug_handler_->GetProperty("debug.gralloc.enable_fb_ubwc", &ubwc_framebuffer);
+  }
+
+  return (ubwc_framebuffer == 1);
+}
+
+bool Debug::IsAVRDisabled() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sdm.debug.disable_avr", &value);
+
+  return (value == 1);
+}
+
+bool Debug::IsExtAnimDisabled() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sys.disable_ext_animation", &value);
+
+  return (value == 1);
+}
+
+bool Debug::IsPartialSplitDisabled() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sdm.debug.disable_partial_split", &value);
+
+  return (value == 1);
+}
+
+DisplayError Debug::GetMixerResolution(uint32_t *width, uint32_t *height) {
+  char value[64] = {};
+
+  DisplayError error = debug_.debug_handler_->GetProperty("sdm.mixer_resolution", value);
+  if (error !=kErrorNone) {
+    return error;
+  }
+
+  std::string str(value);
+
+  *width = UINT32(stoi(str));
+  *height = UINT32(stoi(str.substr(str.find('x') + 1)));
+
+  return kErrorNone;
+}
+
+int Debug::GetExtMaxlayers() {
+  int max_external_layers = 0;
+  debug_.debug_handler_->GetProperty("sdm.max_external_layers", &max_external_layers);
+
+  return std::max(max_external_layers, 2);
+}
+
+bool Debug::GetProperty(const char* property_name, char* value) {
+  if (debug_.debug_handler_->GetProperty(property_name, value) != kErrorNone) {
+    return false;
+  }
+
+  return true;
+}
+
+bool Debug::SetProperty(const char* property_name, const char* value) {
+  if (debug_.debug_handler_->SetProperty(property_name, value) != kErrorNone) {
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/utils/formats.cpp b/sdm845/sdm/libs/utils/formats.cpp
new file mode 100644
index 0000000..b7deb18
--- /dev/null
+++ b/sdm845/sdm/libs/utils/formats.cpp
@@ -0,0 +1,131 @@
+/*
+* Copyright (c) 2016-2017, 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/formats.h>
+
+#define __CLASS__ "FormatsUtils"
+
+namespace sdm {
+
+bool IsUBWCFormat(LayerBufferFormat format) {
+  switch (format) {
+  case kFormatRGBA8888Ubwc:
+  case kFormatRGBX8888Ubwc:
+  case kFormatBGR565Ubwc:
+  case kFormatYCbCr420SPVenusUbwc:
+  case kFormatRGBA1010102Ubwc:
+  case kFormatRGBX1010102Ubwc:
+  case kFormatYCbCr420TP10Ubwc:
+  case kFormatYCbCr420P010Ubwc:
+    return true;
+  default:
+    return false;
+  }
+}
+
+bool Is10BitFormat(LayerBufferFormat format) {
+  switch (format) {
+  case kFormatRGBA1010102:
+  case kFormatARGB2101010:
+  case kFormatRGBX1010102:
+  case kFormatXRGB2101010:
+  case kFormatBGRA1010102:
+  case kFormatABGR2101010:
+  case kFormatBGRX1010102:
+  case kFormatXBGR2101010:
+  case kFormatRGBA1010102Ubwc:
+  case kFormatRGBX1010102Ubwc:
+  case kFormatYCbCr420P010:
+  case kFormatYCbCr420TP10Ubwc:
+  case kFormatYCbCr420P010Ubwc:
+    return true;
+  default:
+    return false;
+  }
+}
+
+const char *GetFormatString(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 kFormatBGR565:                   return "BGR_565";
+  case kFormatRGBA8888Ubwc:             return "RGBA_8888_UBWC";
+  case kFormatRGBX8888Ubwc:             return "RGBX_8888_UBWC";
+  case kFormatBGR565Ubwc:               return "BGR_565_UBWC";
+  case kFormatYCbCr420Planar:           return "Y_CB_CR_420";
+  case kFormatYCrCb420Planar:           return "Y_CR_CB_420";
+  case kFormatYCrCb420PlanarStride16:   return "Y_CR_CB_420_STRIDE16";
+  case kFormatYCbCr420SemiPlanar:       return "Y_CBCR_420";
+  case kFormatYCrCb420SemiPlanar:       return "Y_CRCB_420";
+  case kFormatYCbCr420SemiPlanarVenus:  return "Y_CBCR_420_VENUS";
+  case kFormatYCrCb420SemiPlanarVenus:  return "Y_CRCB_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";
+  case kFormatCbYCrY422H2V1Packed:      return "CBYCRY_422_H2V1";
+  case kFormatRGBA1010102:              return "RGBA_1010102";
+  case kFormatARGB2101010:              return "ARGB_2101010";
+  case kFormatRGBX1010102:              return "RGBX_1010102";
+  case kFormatXRGB2101010:              return "XRGB_2101010";
+  case kFormatBGRA1010102:              return "BGRA_1010102";
+  case kFormatABGR2101010:              return "ABGR_2101010";
+  case kFormatBGRX1010102:              return "BGRX_1010102";
+  case kFormatXBGR2101010:              return "XBGR_2101010";
+  case kFormatRGBA1010102Ubwc:          return "RGBA_1010102_UBWC";
+  case kFormatRGBX1010102Ubwc:          return "RGBX_1010102_UBWC";
+  case kFormatYCbCr420P010:             return "Y_CBCR_420_P010";
+  case kFormatYCbCr420TP10Ubwc:         return "Y_CBCR_420_TP10_UBWC";
+  case kFormatYCbCr420P010Ubwc:         return "Y_CBCR_420_P010_UBWC";
+  default:                              return "UNKNOWN";
+  }
+}
+
+BufferLayout GetBufferLayout(LayerBufferFormat format) {
+  switch (format) {
+  case kFormatYCbCr420TP10Ubwc:
+    return kTPTiled;
+  default:
+    return (IsUBWCFormat(format) ? kUBWC : kLinear);
+  }
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/utils/rect.cpp b/sdm845/sdm/libs/utils/rect.cpp
new file mode 100644
index 0000000..b0cd536
--- /dev/null
+++ b/sdm845/sdm/libs/utils/rect.cpp
@@ -0,0 +1,265 @@
+/*
+* Copyright (c) 2015-2017, 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>
+#include <algorithm>
+
+#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 = std::max(rect1.left, rect2.left);
+  res.top = std::max(rect1.top, rect2.top);
+  res.right = std::min(rect1.right, rect2.right);
+  res.bottom = std::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 = std::min(rect1.left, rect2.left);
+  res.top = std::min(rect1.top, rect2.top);
+  res.right = std::max(rect1.right, rect2.right);
+  res.bottom = std::max(rect1.bottom, rect2.bottom);
+
+  return res;
+}
+
+void SplitLeftRight(const LayerRect &in_rect, uint32_t split_count, uint32_t align_x,
+                    bool flip_horizontal, LayerRect *out_rects) {
+  LayerRect rect_temp = in_rect;
+
+  uint32_t split_width = UINT32(rect_temp.right - rect_temp.left) / split_count;
+  float aligned_width = FLOAT(CeilToMultipleOf(split_width, align_x));
+
+  for (uint32_t count = 0; count < split_count; count++) {
+    float aligned_right = rect_temp.left + aligned_width;
+    out_rects[count].left = rect_temp.left;
+    out_rects[count].right = std::min(rect_temp.right, aligned_right);
+    out_rects[count].top = rect_temp.top;
+    out_rects[count].bottom = rect_temp.bottom;
+
+    rect_temp.left = out_rects[count].right;
+
+    Log(kTagRotator, "SplitLeftRight", out_rects[count]);
+  }
+
+  // If we have a horizontal flip, then we should be splitting the source from right to left
+  // to ensure that the right split will have an aligned width that matches the alignment on the
+  // destination.
+  if (flip_horizontal && split_count > 1) {
+    out_rects[0].right = out_rects[0].left + (out_rects[1].right - out_rects[1].left);
+    out_rects[1].left = out_rects[0].right;
+    Log(kTagRotator, "Adjusted Left", out_rects[0]);
+    Log(kTagRotator, "Adjusted Right", out_rects[1]);
+  }
+}
+
+void SplitTopBottom(const LayerRect &in_rect, uint32_t split_count, uint32_t align_y,
+                    bool flip_horizontal, LayerRect *out_rects) {
+  LayerRect rect_temp = in_rect;
+
+  uint32_t split_height = UINT32(rect_temp.bottom - rect_temp.top) / split_count;
+  float aligned_height = FLOAT(CeilToMultipleOf(split_height, align_y));
+
+  for (uint32_t count = 0; count < split_count; count++) {
+    float aligned_bottom = rect_temp.top + aligned_height;
+    out_rects[count].top = rect_temp.top;
+    out_rects[count].bottom = std::min(rect_temp.bottom, aligned_bottom);
+    out_rects[count].left = rect_temp.left;
+    out_rects[count].right = rect_temp.right;
+
+    rect_temp.top = out_rects[count].bottom;
+
+    Log(kTagRotator, "SplitTopBottom", out_rects[count]);
+  }
+
+  // If we have a horizontal flip, then we should be splitting the destination from bottom to top
+  // to ensure that the bottom split's y-offset is aligned correctly after we swap the destinations
+  // while accounting for the flip.
+  if (flip_horizontal && split_count > 1) {
+    out_rects[0].bottom = out_rects[0].top + (out_rects[1].bottom - out_rects[1].top);
+    out_rects[1].top = out_rects[0].bottom;
+    Log(kTagRotator, "Adjusted Top", out_rects[0]);
+    Log(kTagRotator, "Adjusted Bottom", out_rects[1]);
+  }
+}
+
+void MapRect(const LayerRect &src_domain, const LayerRect &dst_domain, const LayerRect &in_rect,
+             LayerRect *out_rect) {
+  if (!IsValid(src_domain) || !IsValid(dst_domain) || !IsValid(in_rect)) {
+    return;
+  }
+
+  int x_offset = INT(src_domain.left);
+  int y_offset = INT(src_domain.top);
+
+  LayerRect modified_in_rect = Reposition(in_rect, -x_offset, -y_offset);
+  float src_domain_width = src_domain.right - src_domain.left;
+  float src_domain_height = src_domain.bottom - src_domain.top;
+  float dst_domain_width = dst_domain.right - dst_domain.left;
+  float dst_domain_height = dst_domain.bottom - dst_domain.top;
+
+  float width_ratio = dst_domain_width / src_domain_width;
+  float height_ratio = dst_domain_height / src_domain_height;
+
+  out_rect->left = dst_domain.left + (width_ratio * modified_in_rect.left);
+  out_rect->top = dst_domain.top + (height_ratio * modified_in_rect.top);
+  out_rect->right = dst_domain.left + (width_ratio * modified_in_rect.right);
+  out_rect->bottom = dst_domain.top + (height_ratio * modified_in_rect.bottom);
+}
+
+void TransformHV(const LayerRect &src_domain, const LayerRect &in_rect,
+                 const LayerTransform &transform, LayerRect *out_rect) {
+  if (!IsValid(src_domain) || !IsValid(in_rect)) {
+    return;
+  }
+
+  float in_width = in_rect.right - in_rect.left;
+  float in_height = in_rect.bottom - in_rect.top;
+  float x_offset = in_rect.left - src_domain.left;
+  float y_offset = in_rect.top - src_domain.top;
+  *out_rect = in_rect;
+
+  if (transform.flip_horizontal) {
+    out_rect->right = src_domain.right - x_offset;
+    out_rect->left = out_rect->right - in_width;
+  }
+
+  if (transform.flip_vertical) {
+    out_rect->bottom = src_domain.bottom - y_offset;
+    out_rect->top = out_rect->bottom - in_height;
+  }
+}
+
+RectOrientation GetOrientation(const LayerRect &in_rect) {
+  if (!IsValid(in_rect)) {
+    return kOrientationUnknown;
+  }
+
+  float input_width = in_rect.right - in_rect.left;
+  float input_height = in_rect.bottom - in_rect.top;
+
+  if (input_width < input_height) {
+    return kOrientationPortrait;
+  }
+
+  return kOrientationLandscape;
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/utils/sys.cpp b/sdm845/sdm/libs/utils/sys.cpp
new file mode 100644
index 0000000..f5e0f29
--- /dev/null
+++ b/sdm845/sdm/libs/utils/sys.cpp
@@ -0,0 +1,95 @@
+/*
+* 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/sys.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string>
+
+#define __CLASS__ "Sys"
+
+namespace sdm {
+
+#ifndef SDM_VIRTUAL_DRIVER
+
+int PthreadCancel(pthread_t /* thread */) {
+  return 0;
+}
+
+// Pointer to actual driver interfaces.
+Sys::ioctl Sys::ioctl_ = ::ioctl;
+Sys::access Sys::access_ = ::access;
+Sys::open Sys::open_ = ::open;
+Sys::close Sys::close_ = ::close;
+Sys::poll Sys::poll_ = ::poll;
+Sys::pread Sys::pread_ = ::pread;
+Sys::pwrite Sys::pwrite_ = ::pwrite;
+Sys::pthread_cancel Sys::pthread_cancel_ = PthreadCancel;
+Sys::dup Sys::dup_ = ::dup;
+Sys::read Sys::read_ = ::read;
+Sys::write Sys::write_ = ::write;
+Sys::eventfd Sys::eventfd_ = ::eventfd;
+
+bool Sys::getline_(fstream &fs, std::string &line) {
+  return std::getline(fs, line) ? true : false;
+}
+
+#endif  // SDM_VIRTUAL_DRIVER
+
+DynLib::~DynLib() {
+  Close();
+}
+
+bool DynLib::Open(const char *lib_name) {
+  Close();
+  lib_ = ::dlopen(lib_name, RTLD_NOW);
+
+  return (lib_ != NULL);
+}
+
+bool DynLib::Sym(const char *func_name, void **func_ptr) {
+  if (lib_) {
+    *func_ptr = ::dlsym(lib_, func_name);
+  } else {
+    *func_ptr = NULL;
+  }
+
+  return (*func_ptr != NULL);
+}
+
+void DynLib::Close() {
+  if (lib_) {
+    ::dlclose(lib_);
+    lib_ = NULL;
+  }
+}
+
+}  // namespace sdm
+
diff --git a/sdm845/sdm/libs/utils/utils.cpp b/sdm845/sdm/libs/utils/utils.cpp
new file mode 100644
index 0000000..07211a1
--- /dev/null
+++ b/sdm845/sdm/libs/utils/utils.cpp
@@ -0,0 +1,71 @@
+/*
+* Copyright (c) 2016 - 2017, 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 <unistd.h>
+#include <math.h>
+#include <utils/sys.h>
+#include <utils/utils.h>
+
+#include <algorithm>
+
+#define __CLASS__ "Utils"
+
+namespace sdm {
+
+float gcd(float a, float b) {
+  if (a < b) {
+    std::swap(a, b);
+  }
+
+  while (b != 0) {
+    float tmp = b;
+    b = fmodf(a, b);
+    a = tmp;
+  }
+
+  return a;
+}
+
+float lcm(float a, float b) {
+  return (a * b) / gcd(a, b);
+}
+
+void CloseFd(int *fd) {
+  if (*fd >= 0) {
+    Sys::close_(*fd);
+    *fd = -1;
+  }
+}
+
+DriverType GetDriverType() {
+    const char *fb_caps = "/sys/devices/virtual/graphics/fb0/mdp/caps";
+    // 0 - File exists
+    return Sys::access_(fb_caps, F_OK) ? DriverType::DRM : DriverType::FB;
+}
+}  // namespace sdm