Merge "sdm: Use monotonic clock in HAL" into display.lnx.5.0
diff --git a/Android.mk b/Android.mk
index 44393b0..a4d5687 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,3 +1,4 @@
+ifneq ($(TARGET_DISABLE_DISPLAY),true)
 sdm-libs := sdm/libs
 display-hals := include libqservice libqdutils $(sdm-libs)/utils $(sdm-libs)/core
 
@@ -15,3 +16,4 @@
     include $(call all-named-subdir-makefiles,$(display-hals))
 endif
 endif
+endif #TARGET_DISABLE_DISPLAY
diff --git a/gpu_tonemapper/EGLImageWrapper.cpp b/gpu_tonemapper/EGLImageWrapper.cpp
index dfc16d8..19bf093 100644
--- a/gpu_tonemapper/EGLImageWrapper.cpp
+++ b/gpu_tonemapper/EGLImageWrapper.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -22,10 +22,19 @@
 #include <gralloc_priv.h>
 #include <ui/GraphicBuffer.h>
 #include <fcntl.h>
-#include <linux/msm_ion.h>
+#include <string>
+#include <map>
+#include <utility>
 
+using std::string;
+using std::map;
+using std::pair;
+
+static string pidString = std::to_string(getpid());
+
+#ifndef TARGET_ION_ABI_VERSION
 //-----------------------------------------------------------------------------
-void free_ion_cookie(int ion_fd, int cookie)
+static void free_ion_cookie(int ion_fd, int cookie)
 //-----------------------------------------------------------------------------
 {
   if (ion_fd && !ioctl(ion_fd, ION_IOC_FREE, &cookie)) {
@@ -35,120 +44,169 @@
 }
 
 //-----------------------------------------------------------------------------
-int get_ion_cookie(int ion_fd, int fd)
+static int get_ion_cookie(int ion_fd, int fd)
 //-----------------------------------------------------------------------------
 {
-   int cookie = fd;
+  int cookie = fd;
 
-   struct ion_fd_data fdData;
-   memset(&fdData, 0, sizeof(fdData));
-   fdData.fd = 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);
-   }
+  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;
+  return cookie;
 }
-
+#else
 //-----------------------------------------------------------------------------
-EGLImageWrapper::DeleteEGLImageCallback::DeleteEGLImageCallback(int fd)
+static string get_ion_buff_str(int buff_fd)
 //-----------------------------------------------------------------------------
 {
-    ion_fd = fd;
-}
-
-//-----------------------------------------------------------------------------
-void EGLImageWrapper::DeleteEGLImageCallback::operator()(int& k, EGLImageBuffer*& eglImage)
-//-----------------------------------------------------------------------------
-{
-    free_ion_cookie(ion_fd,  k);
-    if( eglImage != 0 )
-    {
-        delete eglImage;
+  string retStr = {};
+  if (buff_fd >= 0) {
+    string fdString = std::to_string(buff_fd);
+    string symlinkPath = "/proc/"+pidString+"/fd/"+fdString;
+    char buffer[1024] = {};
+    ssize_t ret = ::readlink(symlinkPath.c_str(), buffer, sizeof(buffer) - 1);
+    if (ret != -1) {
+      buffer[ret] = '\0';
+      retStr = buffer;
     }
+  }
+
+  return retStr;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+void EGLImageWrapper::DeleteEGLImageCallback::operator()(int& buffInt, EGLImageBuffer*& eglImage)
+//-----------------------------------------------------------------------------
+{
+  if (eglImage != 0) {
+    delete eglImage;
+  }
+
+#ifndef TARGET_ION_ABI_VERSION
+  free_ion_cookie(ion_fd, buffInt /* cookie */);
+#else
+  if (!mapClearPending) {
+    for (auto it = buffStrbuffIntMapPtr->begin(); it != buffStrbuffIntMapPtr->end(); it++) {
+      if (it->second == buffInt /* counter */) {
+        buffStrbuffIntMapPtr->erase(it);
+        return;
+      }
+    }
+  }
+#endif
 }
 
 //-----------------------------------------------------------------------------
 EGLImageWrapper::EGLImageWrapper()
 //-----------------------------------------------------------------------------
 {
-    eglImageBufferMap = new android::LruCache<int, EGLImageBuffer*>(32);
-    ion_fd = open("/dev/ion", O_RDONLY);
-    callback = new DeleteEGLImageCallback(ion_fd);
-    eglImageBufferMap->setOnEntryRemovedListener(callback);
+  eglImageBufferCache = new android::LruCache<int, EGLImageBuffer*>(32);
+  callback = new DeleteEGLImageCallback(&buffStrbuffIntMap);
+  eglImageBufferCache->setOnEntryRemovedListener(callback);
+
+#ifndef TARGET_ION_ABI_VERSION
+  ion_fd = open("/dev/ion", O_RDONLY);
+  callback->ion_fd = ion_fd;
+#endif
 }
 
 //-----------------------------------------------------------------------------
 EGLImageWrapper::~EGLImageWrapper()
 //-----------------------------------------------------------------------------
 {
-    if( eglImageBufferMap != 0 )
-    {
-        eglImageBufferMap->clear();
-        delete eglImageBufferMap;
-        eglImageBufferMap = 0;
+  if (eglImageBufferCache != 0) {
+    if (callback != 0) {
+      callback->mapClearPending = true;
     }
+    eglImageBufferCache->clear();
+    delete eglImageBufferCache;
+    eglImageBufferCache = 0;
+    buffStrbuffIntMap.clear();
+  }
 
-    if( callback != 0 )
-    {
-        delete callback;
-        callback = 0;
-    }
+  if (callback != 0) {
+    delete callback;
+    callback = 0;
+  }
 
-    if( ion_fd > 0 )
-    {
-        close(ion_fd);
-    }
+#ifndef TARGET_ION_ABI_VERSION
+  if (ion_fd > 0) {
+    close(ion_fd);
     ion_fd = -1;
+  }
+#endif
 }
+
 //-----------------------------------------------------------------------------
 static EGLImageBuffer* L_wrap(const private_handle_t *src)
 //-----------------------------------------------------------------------------
 {
-    EGLImageBuffer* result = 0;
+  EGLImageBuffer* result = 0;
 
-    native_handle_t *native_handle = const_cast<private_handle_t *>(src);
+  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;
+  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;
-    }
+  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,
+  android::sp<android::GraphicBuffer> graphicBuffer =
+    new android::GraphicBuffer(src->unaligned_width, src->unaligned_height, src->format,
 #ifndef __NOUGAT__
-                                   1, // Layer count
+                               1,  // Layer count
 #endif
-                                   flags, src->width /*src->stride*/,
-                                   native_handle, false);
+                               flags, src->width /*src->stride*/,
+                               native_handle, false);
 
-    result = new EGLImageBuffer(graphicBuffer);
+  result = new EGLImageBuffer(graphicBuffer);
 
-    return result;
+  return result;
 }
 
 //-----------------------------------------------------------------------------
 EGLImageBuffer *EGLImageWrapper::wrap(const void *pvt_handle)
 //-----------------------------------------------------------------------------
 {
-    const private_handle_t *src = static_cast<const private_handle_t *>(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 )
-    {
+#ifndef TARGET_ION_ABI_VERSION
+  int ion_cookie = get_ion_cookie(ion_fd, src->fd);
+  EGLImageBuffer* eglImage = nullptr;
+  eglImage = eglImageBufferCache->get(ion_cookie);
+  if (eglImage == 0) {
+    eglImage = L_wrap(src);
+    eglImageBufferCache->put(ion_cookie, eglImage);
+  } else {
+    free_ion_cookie(ion_fd, ion_cookie);
+  }
+#else
+  string buffStr = get_ion_buff_str(src->fd);
+  EGLImageBuffer* eglImage = nullptr;
+  if (!buffStr.empty()) {
+    auto it = buffStrbuffIntMap.find(buffStr);
+    if (it != buffStrbuffIntMap.end()) {
+      eglImage = eglImageBufferCache->get(it->second);
+    } else {
         eglImage = L_wrap(src);
-        eglImageBufferMap->put(ion_cookie, eglImage);
+        buffStrbuffIntMap.insert(pair<string, int>(buffStr, buffInt));
+        eglImageBufferCache->put(buffInt, eglImage);
+        buffInt++;
     }
-    else {
-        free_ion_cookie(ion_fd, ion_cookie);
-    }
+  } else {
+    ALOGE("Could not provide an eglImage for fd = %d, EGLImageWrapper = %p", src->fd, this);
+  }
+#endif
 
-    return eglImage;
+  return eglImage;
 }
diff --git a/gpu_tonemapper/EGLImageWrapper.h b/gpu_tonemapper/EGLImageWrapper.h
index e9a4d68..296aa66 100644
--- a/gpu_tonemapper/EGLImageWrapper.h
+++ b/gpu_tonemapper/EGLImageWrapper.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -21,27 +21,40 @@
 #define __TONEMAPPER_EGLIMAGEWRAPPER_H__
 
 #include <utils/LruCache.h>
+#include <linux/msm_ion.h>
+#include <string>
+#include <map>
 #include "EGLImageBuffer.h"
 
+using std::string;
+using std::map;
+
 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);
-        };
+ private:
+  class DeleteEGLImageCallback : public android::OnEntryRemoved<int, EGLImageBuffer*> {
+   public:
+     explicit DeleteEGLImageCallback(map<string, int>* mapPtr) { buffStrbuffIntMapPtr = mapPtr; }
+     void operator()(int& buffInt, EGLImageBuffer*& eglImage);
+     map<string, int>* buffStrbuffIntMapPtr = nullptr;
+     bool mapClearPending = false;
+   #ifndef TARGET_ION_ABI_VERSION
+     int ion_fd = -1;
+   #endif
+  };
 
-        android::LruCache<int, EGLImageBuffer *>* eglImageBufferMap;
-        DeleteEGLImageCallback* callback;
-        int ion_fd;
+  android::LruCache<int, EGLImageBuffer *>* eglImageBufferCache;
+  map<string, int> buffStrbuffIntMap = {};
+  DeleteEGLImageCallback* callback = 0;
+ #ifndef TARGET_ION_ABI_VERSION
+   int ion_fd = -1;
+ #else
+   uint64_t buffInt = 0;
+ #endif
 
-    public:
-        EGLImageWrapper();
-        ~EGLImageWrapper();
-        EGLImageBuffer* wrap(const void *pvt_handle);
+ public:
+  EGLImageWrapper();
+  ~EGLImageWrapper();
+  EGLImageBuffer* wrap(const void *pvt_handle);
 };
 
-#endif  //__TONEMAPPER_EGLIMAGEWRAPPER_H__
+#endif  // __TONEMAPPER_EGLIMAGEWRAPPER_H__
diff --git a/gpu_tonemapper/Tonemapper.cpp b/gpu_tonemapper/Tonemapper.cpp
index 811e091..2605c7f 100644
--- a/gpu_tonemapper/Tonemapper.cpp
+++ b/gpu_tonemapper/Tonemapper.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -137,10 +137,14 @@
   }
 
   // set destination
-  engine_setDestination(dst_buffer->getFramebuffer(), 0, 0, dst_buffer->getWidth(),
-                        dst_buffer->getHeight());
+  if (dst_buffer) {
+    engine_setDestination(dst_buffer->getFramebuffer(), 0, 0, dst_buffer->getWidth(),
+                          dst_buffer->getHeight());
+  }
   // set source
-  engine_setExternalInputBuffer(0, src_buffer->getTexture());
+  if (src_buffer) {
+    engine_setExternalInputBuffer(0, src_buffer->getTexture());
+  }
   // set 3d lut
   engine_set3DInputBuffer(1, tonemapTexture);
   // set non-uniform xform
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 97660ea..fc40b2e 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -60,6 +60,12 @@
    */
   PLANE_SET_DST_RECT,
   /*
+   * Op: Sets plane exclusion rect
+   * Arg: uint32_t - Plane ID
+   *      drm_clip_rect - Exclusion Rectangle
+   */
+  PLANE_SET_EXCL_RECT,
+  /*
    * Op: Sets plane zorder
    * Arg: uint32_t - Plane ID
    *      uint32_t - zorder
@@ -150,6 +156,12 @@
    */
   PLANE_SET_MULTIRECT_MODE,
   /*
+   * Op: Sets rotator output frame buffer ID for plane.
+   * Arg: uint32_t - Plane ID
+   *      uint32_t - Framebuffer ID
+   */
+  PLANE_SET_ROT_FB_ID,
+  /*
    * Op: Activate or deactivate a CRTC
    * Arg: uint32_t - CRTC ID
    *      uint32_t - 1 to enable, 0 to disable
@@ -211,6 +223,12 @@
    */
   CRTC_SET_DRAM_IB,
   /*
+   * Op: Sets Rotator BW for inline rotation
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - rot_bw
+   */
+  CRTC_SET_ROT_PREFILL_BW,
+  /*
    * Op: Sets rotator clock for inline rotation
    * Arg: uint32_t - CRTC ID
    *      uint32_t - rot_clk
@@ -377,6 +395,14 @@
 enum struct SmartDMARevision {
   V1,
   V2,
+  V2p5
+};
+
+/* Inline Rotation version */
+enum struct InlineRotationVersion {
+  UNKNOWN,
+  V1,
+  V1p1,   // Rotator FB ID needs to be set
 };
 
 /* Per CRTC Resource Info*/
@@ -428,14 +454,17 @@
   // FourCC format enum and modifier
   std::vector<std::pair<uint32_t, uint64_t>> formats_supported;
   uint32_t max_linewidth;
+  uint32_t max_scaler_linewidth;
   uint32_t max_upscale;
   uint32_t max_downscale;
   uint32_t max_horizontal_deci;
   uint32_t max_vertical_deci;
   uint64_t max_pipe_bandwidth;
   uint32_t cache_size;  // cache size in bytes for inline rotation support.
+  bool has_excl_rect = false;
   QSEEDStepVersion qseed3_version;
   bool multirect_prop_present = false;
+  InlineRotationVersion inrot_version;  // inline rotation version
 };
 
 // All DRM Planes as map<Plane_id , plane_type_info> listed from highest to lowest priority
@@ -592,11 +621,12 @@
   /* Perform request operation.
    *
    * [input]: opcode: operation code from DRMOps list.
+   *          obj_id: Relevant crtc, connector, plane id
    *          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;
+  virtual int Perform(DRMOps opcode, uint32_t obj_id, ...) = 0;
 
   /*
    * Commit the params set via Perform(). Also resets the properties after commit. Needs to be
diff --git a/libgralloc1/Android.mk b/libgralloc1/Android.mk
index cdb651c..49ceae5 100644
--- a/libgralloc1/Android.mk
+++ b/libgralloc1/Android.mk
@@ -8,12 +8,14 @@
 LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) \
-                                 external/libcxx/include/
+                                 external/libcxx/include/ \
+                                 system/core/libion/include/ \
+                                 system/core/libion/kernel-headers/ \
+                                 $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
 
 LOCAL_HEADER_LIBRARIES        := display_headers
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdMetaData libsync libgrallocutils
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdMetaData libsync libgrallocutils libion
 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 \
diff --git a/libgralloc1/gr_allocator.cpp b/libgralloc1/gr_allocator.cpp
index 066ac34..7a54187 100644
--- a/libgralloc1/gr_allocator.cpp
+++ b/libgralloc1/gr_allocator.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 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
@@ -49,6 +49,10 @@
 #define ION_FLAG_CP_CAMERA_PREVIEW 0
 #endif
 
+#ifndef ION_SECURE
+#define ION_SECURE ION_FLAG_SECURE
+#endif
+
 #ifdef MASTER_SIDE_CP
 #define CP_HEAP_ID ION_SECURE_HEAP_ID
 #define SD_HEAP_ID ION_SECURE_DISPLAY_HEAP_ID
@@ -137,9 +141,10 @@
   return -EINVAL;
 }
 
-int Allocator::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op) {
+int Allocator::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op,
+                           int fd) {
   if (ion_allocator_) {
-    return ion_allocator_->CleanBuffer(base, size, offset, handle, op);
+    return ion_allocator_->CleanBuffer(base, size, offset, handle, op, fd);
   }
 
   return -EINVAL;
@@ -207,7 +212,11 @@
     } else if (prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_10BIT) {
       gr_format = HAL_PIXEL_FORMAT_YCbCr_420_P010_VENUS;
     } else if (cons_usage & GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER) {
-      gr_format = HAL_PIXEL_FORMAT_NV12_ENCODEABLE;  // NV12
+      if (prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_VIDEO_NV21_ENCODER) {
+        gr_format = HAL_PIXEL_FORMAT_NV21_ENCODEABLE;  // NV21
+      } else {
+        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
diff --git a/libgralloc1/gr_allocator.h b/libgralloc1/gr_allocator.h
index d57f50e..c059ba6 100644
--- a/libgralloc1/gr_allocator.h
+++ b/libgralloc1/gr_allocator.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 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
@@ -52,7 +52,7 @@
   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 CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op, int fd);
   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
diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp
index 815f2b0..8a1403a 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -329,7 +329,7 @@
   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)) {
+                                buf->ion_handle_main, CACHE_INVALIDATE, hnd->fd)) {
       return GRALLOC1_ERROR_BAD_HANDLE;
     }
   }
@@ -355,7 +355,7 @@
 
   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) {
+                                buf->ion_handle_main, CACHE_CLEAN, hnd->fd) != 0) {
       status = GRALLOC1_ERROR_BAD_HANDLE;
     }
     hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
@@ -517,8 +517,11 @@
   hnd->base_metadata = 0;
   hnd->layer_count = layer_count;
 
-  ColorSpace_t colorSpace = ITU_R_601;
-  setMetaData(hnd, UPDATE_COLOR_SPACE, reinterpret_cast<void *>(&colorSpace));
+  if (buffer_type == BUFFER_TYPE_VIDEO) {
+    // set default csc to 601L for only video buffers
+    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);
diff --git a/libgralloc1/gr_ion_alloc.cpp b/libgralloc1/gr_ion_alloc.cpp
index c8300ab..4fc67f4 100644
--- a/libgralloc1/gr_ion_alloc.cpp
+++ b/libgralloc1/gr_ion_alloc.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 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
@@ -31,6 +31,11 @@
 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
 #include <sys/ioctl.h>
 #include <sys/mman.h>
+#include <linux/msm_ion.h>
+#if TARGET_ION_ABI_VERSION >= 2
+#include <ion/ion.h>
+#include <linux/dma-buf.h>
+#endif
 #include <stdlib.h>
 #include <fcntl.h>
 #include <cutils/log.h>
@@ -47,7 +52,7 @@
 
 bool IonAlloc::Init() {
   if (ion_dev_fd_ == FD_INIT) {
-    ion_dev_fd_ = open(kIonDevice, O_RDONLY);
+    ion_dev_fd_ = OpenIonDevice();
   }
 
   if (ion_dev_fd_ < 0) {
@@ -59,6 +64,103 @@
   return true;
 }
 
+#if TARGET_ION_ABI_VERSION >= 2  // Use libion APIs for new ion
+
+int IonAlloc::OpenIonDevice() {
+  return ion_open();
+}
+
+void IonAlloc::CloseIonDevice() {
+  if (ion_dev_fd_ > FD_INIT) {
+    ion_close(ion_dev_fd_);
+  }
+
+  ion_dev_fd_ = FD_INIT;
+}
+
+int IonAlloc::AllocBuffer(AllocData *data) {
+  ATRACE_CALL();
+  int err = 0;
+  int fd = -1;
+  unsigned int flags = data->flags;
+
+  flags |= data->uncached ? 0 : ION_FLAG_CACHED;
+
+  std::string tag_name{};
+  if (ATRACE_ENABLED()) {
+    tag_name = "libion alloc size: " + std::to_string(data->size);
+  }
+
+  ATRACE_BEGIN(tag_name.c_str());
+  err = ion_alloc_fd(ion_dev_fd_, data->size, data->align, data->heap_id, flags, &fd);
+  ATRACE_END();
+  if (err) {
+    ALOGE("libion alloc failed");
+    return err;
+  }
+
+  data->fd = fd;
+  data->ion_handle = fd;  // For new ion api ion_handle does not exists so reusing fd for now
+  ALOGD_IF(DEBUG, "libion: Allocated buffer size:%u fd:%d", data->size, data->fd);
+
+  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, "libion: Freeing buffer base:%p size:%u fd:%d", base, size, fd);
+
+  if (base) {
+    err = UnmapBuffer(base, size, offset);
+  }
+
+  close(fd);
+  return err;
+}
+
+int IonAlloc::ImportBuffer(int fd) {
+  // For new ion api ion_handle does not exists so reusing fd for now
+  return fd;
+}
+
+int IonAlloc::CleanBuffer(void */*base*/, unsigned int /*size*/, unsigned int /*offset*/,
+                          int /*handle*/, int op, int dma_buf_fd) {
+  ATRACE_CALL();
+  ATRACE_INT("operation id", op);
+
+  struct dma_buf_sync sync;
+  int err = 0;
+
+  switch (op) {
+    case CACHE_CLEAN:
+      sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
+      break;
+    case CACHE_INVALIDATE:
+      sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
+      break;
+    default:
+      ALOGE("%s: Invalid operation %d", __FUNCTION__, op);
+      return -1;
+  }
+
+  if (ioctl(dma_buf_fd, INT(DMA_BUF_IOCTL_SYNC), &sync)) {
+    err = -errno;
+    ALOGE("%s: DMA_BUF_IOCTL_SYNC failed with error - %s", __FUNCTION__, strerror(errno));
+    return err;
+  }
+
+  return 0;
+}
+
+#else
+#ifndef TARGET_ION_ABI_VERSION  // Use old ion apis directly
+
+int IonAlloc::OpenIonDevice() {
+  return open(kIonDevice, O_RDONLY);
+}
+
 void IonAlloc::CloseIonDevice() {
   if (ion_dev_fd_ > FD_INIT) {
     close(ion_dev_fd_);
@@ -131,25 +233,6 @@
   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;
@@ -162,20 +245,8 @@
   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) {
+int IonAlloc::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op,
+                          int /*fd*/) {
   ATRACE_CALL();
   ATRACE_INT("operation id", op);
   struct ion_flush_data flush_data;
@@ -210,4 +281,65 @@
   return 0;
 }
 
+#else  // This ion version is not supported
+
+int IonAlloc::OpenIonDevice() {
+  return -EINVAL;
+}
+
+void IonAlloc::CloseIonDevice() {
+}
+
+int IonAlloc::AllocBuffer(AllocData * /*data*/) {
+  return -EINVAL;
+}
+
+int IonAlloc::FreeBuffer(void * /*base*/, unsigned int /*size*/, unsigned int /*offset*/,
+                         int /*fd*/, int /*ion_handle*/) {
+  return -EINVAL;
+}
+
+int IonAlloc::ImportBuffer(int /*fd*/) {
+  return -EINVAL;
+}
+
+int IonAlloc::CleanBuffer(void * /*base*/, unsigned int /*size*/, unsigned int /*offset*/,
+                          int /*handle*/, int /*op*/, int /*fd*/) {
+  return -EINVAL;
+}
+
+#endif
+#endif  // TARGET_ION_ABI_VERSION
+
+
+int IonAlloc::MapBuffer(void **base, unsigned int size, unsigned int offset, int fd) {
+  ATRACE_CALL();
+  int err = 0;
+  void *addr = 0;
+
+  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::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;
+}
+
 }  // namespace gralloc1
diff --git a/libgralloc1/gr_ion_alloc.h b/libgralloc1/gr_ion_alloc.h
index b25f509..b41f5f1 100644
--- a/libgralloc1/gr_ion_alloc.h
+++ b/libgralloc1/gr_ion_alloc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 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
@@ -68,10 +68,12 @@
   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);
+  int CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op, int fd);
 
  private:
+#ifndef TARGET_ION_ABI_VERSION
   const char *kIonDevice = "/dev/ion";
+#endif
 
   int OpenIonDevice();
   void CloseIonDevice();
diff --git a/libgralloc1/gr_utils.cpp b/libgralloc1/gr_utils.cpp
index 480ad98..2eb0b11 100644
--- a/libgralloc1/gr_utils.cpp
+++ b/libgralloc1/gr_utils.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 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
@@ -287,6 +287,7 @@
       size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
       break;
     case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_NV21_ENCODEABLE:
       size = VENUS_BUFFER_SIZE(COLOR_FMT_NV21, width, height);
       break;
     case HAL_PIXEL_FORMAT_BLOB:
diff --git a/libgralloc1/gralloc_priv.h b/libgralloc1/gralloc_priv.h
index 7553017..07cc285 100644
--- a/libgralloc1/gralloc_priv.h
+++ b/libgralloc1/gralloc_priv.h
@@ -20,6 +20,7 @@
 #ifndef __GRALLOC_PRIV_H__
 #define __GRALLOC_PRIV_H__
 
+#include <errno.h>
 #include <unistd.h>
 #include "gr_priv_handle.h"
 
@@ -59,6 +60,8 @@
 #define GRALLOC1_PRODUCER_USAGE_PRIVATE_10BIT_TP  0x08000000
 #define GRALLOC1_CONSUMER_USAGE_PRIVATE_10BIT_TP  0x08000000
 
+/* This flag is used to indicate video NV21 format */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_VIDEO_NV21_ENCODER (1ULL << 24)
 
 /* Consumer flags */
 /* TODO(user): Fix when producer and consumer flags are actually separated */
@@ -107,6 +110,7 @@
 #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_NV21_ENCODEABLE 0x7FA30C00
 #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
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 303c89b..1f813ac 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -388,12 +388,13 @@
   /*! @brief Method to set current state of the display device.
 
     @param[in] state \link DisplayState \endlink
+    @param[in] pointer to release fence
 
     @return \link DisplayError \endlink
 
     @sa SetDisplayState
   */
-  virtual DisplayError SetDisplayState(DisplayState state) = 0;
+  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence) = 0;
 
   /*! @brief Method to set active configuration for variable properties of the display device.
 
diff --git a/sdm/include/core/layer_buffer.h b/sdm/include/core/layer_buffer.h
index 649dda4..8f7f6fe 100644
--- a/sdm/include/core/layer_buffer.h
+++ b/sdm/include/core/layer_buffer.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, 2016-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014, 2016-2018, 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:
@@ -149,6 +149,10 @@
   kFormatYCbCr420P010Ubwc,            //!< UBWC aligned YCbCr420P010 format.
 
   kFormatYCbCr420P010Venus,           //!< Venus aligned YCbCr420P010 format.
+                                      //!
+  kFormatYCbCr420SPVenusTile,         //!< Tiled & uncompressed YCbCr420SemiPlanarVenus format
+  kFormatYCbCr420TP10Tile,            //!< Tiled & uncompressed YCbCr420TP10 format.
+  kFormatYCbCr420P010Tile,            //!< Tiled & uncompressed YCbCr420P010 format.
 
   /* All YUV-Packed formats, Any new format will be added towards end of this group to maintain
      backward compatibility.
@@ -278,6 +282,10 @@
   UbwcCrStatsVector  ubwc_crstats[NUM_UBWC_CR_STATS_LAYERS] = {};
                                 //! < UBWC Compression ratio,stats. Stored as a vector of pair of
                                 //! of (tile size, #of tiles)
+  LayerBuffer() {
+    color_metadata.colorPrimaries = ColorPrimaries_BT709_5;
+    color_metadata.transfer = Transfer_sRGB;
+  }
 };
 
 // This enum represents buffer layout types.
diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h
index 867bc05..afa120e 100644
--- a/sdm/include/core/layer_stack.h
+++ b/sdm/include/core/layer_stack.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -35,6 +35,7 @@
 #include <utils/constants.h>
 
 #include <vector>
+#include <utility>
 
 #include "layer_buffer.h"
 #include "sdm_types.h"
@@ -190,6 +191,8 @@
       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 dest_tone_map : 1;  //!< This flag will be set by SDM when the layer needs
+                                   //!< destination tone map
     };
     uint32_t request_flags = 0;  //!< For initialization purpose only.
                                  //!< Shall not be refered directly.
@@ -377,12 +380,28 @@
   LayerSolidFill solid_fill_info = {};             //!< solid fill info along with depth.
 };
 
+/*! @brief This structure defines the color space + transfer of a given layer.
+
+  @sa PrimariesTransfer
+*/
+
+struct PrimariesTransfer {
+  ColorPrimaries primaries = ColorPrimaries_BT709_5;
+  GammaTransfer transfer = Transfer_sRGB;
+
+  bool operator==(const PrimariesTransfer& blend_cs) const {
+    return ((primaries == blend_cs.primaries) && (transfer == blend_cs.transfer));
+  }
+};
+
+
 /*! @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.
 
@@ -400,7 +419,8 @@
 
   LayerStackFlags flags;               //!< Flags associated with this layer set.
 
-  ColorPrimaries blend_cs = ColorPrimaries_BT709_5;  //!< o/p - Blending color space updated by SDM
+
+  PrimariesTransfer blend_cs = {};     //!< o/p - Blending color space of the frame, updated by SDM
 };
 
 }  // namespace sdm
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 52bc73e..bd598e0 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -176,6 +176,13 @@
 enum SmartDMARevision {
   V1,
   V2,
+  V2p5
+};
+
+enum InlineRotationVersion {
+  kInlineRotationNone,
+  kInlineRotationV1,
+  kInlineRotationV1p1,
 };
 
 struct HWResourceInfo {
@@ -198,6 +205,7 @@
   uint64_t max_bandwidth_high = 0;
   uint32_t max_mixer_width = 2048;
   uint32_t max_pipe_width = 2048;
+  uint32_t max_scaler_pipe_width = 2560;
   uint32_t max_cursor_size = 0;
   uint64_t max_pipe_bw =  0;
   uint32_t max_sde_clk = 0;
@@ -220,6 +228,7 @@
   bool has_qseed3 = false;
   bool has_concurrent_writeback = false;
   bool has_ppp = false;
+  bool has_excl_rect = false;
   uint32_t writeback_index = kHWBlockMax;
   HWDynBwLimitInfo dyn_bw_info;
   std::vector<HWPipeCaps> hw_pipes;
@@ -236,6 +245,7 @@
   uint32_t cache_size = 0;  // cache size in bytes
   HWQseedStepVersion pipe_qseed3_version = kQseed3v2;  // only valid when has_qseed3=true
   uint32_t min_prefill_lines = 0;
+  InlineRotationVersion inrot_version = kInlineRotationNone;
 
   void Reset() { *this = HWResourceInfo(); }
 };
@@ -486,6 +496,7 @@
   HWSubBlockType sub_block_type = kHWSubBlockMax;
   LayerRect src_roi;
   LayerRect dst_roi;
+  LayerRect excl_rect;  // exclusion rectangle per pipe rectangle
   uint8_t horizontal_decimation = 0;
   uint8_t vertical_decimation = 0;
   HWScaleData scale_data;
@@ -528,12 +539,18 @@
   HDROperation operation = kNoOp;
 };
 
+struct LayerExt {
+  std::vector<LayerRect> excl_rects = {};  // list of exclusion rects
+};
+
 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
+  std::vector<LayerExt> layer_exts = {};  // Extention layer having list of
+                                          // exclusion rectangles for each layer
 
   std::vector<uint32_t> index;   // Indexes of the layers from the layer stack which need to
                                  // be programmed on hardware.
@@ -560,6 +577,7 @@
   uint64_t llcc_ib_bps = 0;
   uint64_t dram_ab_bps = 0;
   uint64_t dram_ib_bps = 0;
+  uint64_t rot_prefill_bw_bps = 0;
   uint32_t clock_hz = 0;
   uint32_t rot_clock_hz = 0;
 };
diff --git a/sdm/include/utils/formats.h b/sdm/include/utils/formats.h
index 2d43850..f5a7a25 100644
--- a/sdm/include/utils/formats.h
+++ b/sdm/include/utils/formats.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2016 - 2018, 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
@@ -56,6 +56,7 @@
 BufferLayout GetBufferLayout(LayerBufferFormat format);
 DisplayError GetBufferFormatTileSize(LayerBufferFormat format, FormatTileSize *tile_size);
 float GetBufferFormatBpp(LayerBufferFormat format);
+bool HasAlphaChannel(LayerBufferFormat format);
 
 }  // namespace sdm
 
diff --git a/sdm/include/utils/rect.h b/sdm/include/utils/rect.h
index b25f76e..c3fd492 100644
--- a/sdm/include/utils/rect.h
+++ b/sdm/include/utils/rect.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015-2018, 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
@@ -51,6 +51,8 @@
   LayerRect Union(const LayerRect &rect1, const LayerRect &rect2);
   LayerRect Intersection(const LayerRect &rect1, const LayerRect &rect2);
   LayerRect Subtract(const LayerRect &rect1, const LayerRect &rect2);
+  void Subtract(const LayerRect &rect1, const LayerRect &rect2, LayerRect *res);
+  bool Contains(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);
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 383bdba..18241d9 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -430,7 +430,7 @@
   return last_power_mode_;
 }
 
-DisplayError DisplayBase::SetDisplayState(DisplayState state) {
+DisplayError DisplayBase::SetDisplayState(DisplayState state, int *release_fence) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   DisplayError error = kErrorNone;
   bool active = false;
@@ -452,7 +452,7 @@
     break;
 
   case kStateOn:
-    error = hw_intf_->PowerOn();
+    error = hw_intf_->PowerOn(release_fence);
     if (error != kErrorNone) {
       return error;
     }
@@ -468,13 +468,13 @@
     break;
 
   case kStateDoze:
-    error = hw_intf_->Doze();
+    error = hw_intf_->Doze(release_fence);
     active = true;
     last_power_mode_ = kStateDoze;
     break;
 
   case kStateDozeSuspend:
-    error = hw_intf_->DozeSuspend();
+    error = hw_intf_->DozeSuspend(release_fence);
     if (display_type_ != kPrimary) {
       active = true;
     }
@@ -1525,7 +1525,7 @@
     // HDR color mode is set when hdr layer is present in layer_stack.
     // If client flags HDR layer as skipped, then blending happens
     // in SDR color space. Hence, need to restore the SDR color mode.
-    if (layer_stack->blend_cs != ColorPrimaries_BT2020) {
+    if (layer_stack->blend_cs.primaries != ColorPrimaries_BT2020) {
       error = SetHDRMode(false);
       if (error != kErrorNone) {
         DLOGW("Failed to restore SDR mode");
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 014ea11..bd597c9 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2018, 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:
@@ -62,7 +62,7 @@
   virtual DisplayError GetConfig(DisplayConfigFixedInfo *variable_info);
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
-  virtual DisplayError SetDisplayState(DisplayState state);
+  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
   virtual DisplayError SetActiveConfig(uint32_t index);
   virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
     return kErrorNotSupported;
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
index 1f1a051..2076fe5 100644
--- a/sdm/libs/core/display_hdmi.cpp
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -170,7 +170,6 @@
 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);
 
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index 8466f8b..d9fef33 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -166,10 +166,10 @@
   return error;
 }
 
-DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
+DisplayError DisplayPrimary::SetDisplayState(DisplayState state, int *release_fence) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   DisplayError error = kErrorNone;
-  error = DisplayBase::SetDisplayState(state);
+  error = DisplayBase::SetDisplayState(state, release_fence);
   if (error != kErrorNone) {
     return error;
   }
@@ -391,19 +391,26 @@
 
 void DisplayPrimary::ResetPanel() {
   DisplayError status = kErrorNone;
+  int release_fence = -1;
 
   DLOGI("Powering off primary");
-  status = SetDisplayState(kStateOff);
+  status = SetDisplayState(kStateOff, &release_fence);
   if (status != kErrorNone) {
     DLOGE("power-off on primary failed with error = %d", status);
   }
+  if (release_fence >= 0) {
+    ::close(release_fence);
+  }
 
   DLOGI("Restoring power mode on primary");
   DisplayState mode = GetLastPowerMode();
-  status = SetDisplayState(mode);
+  status = SetDisplayState(mode, &release_fence);
   if (status != kErrorNone) {
     DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
   }
+  if (release_fence >= 0) {
+    ::close(release_fence);
+  }
 
   DLOGI("Enabling HWVsync");
   status = SetVSyncState(true);
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index a4dd4b8..e14c6d7 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -44,7 +44,7 @@
   virtual DisplayError Commit(LayerStack *layer_stack);
   virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
   virtual DisplayError DisablePartialUpdateOneFrame();
-  virtual DisplayError SetDisplayState(DisplayState state);
+  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
   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);
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index c734f4c..91f89a2 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -186,6 +186,10 @@
       *drm_format = DRM_FORMAT_NV12;
       *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
       break;
+    case kFormatYCbCr420SPVenusTile:
+      *drm_format = DRM_FORMAT_NV12;
+      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_TILE;
+      break;
     case kFormatYCrCb420SemiPlanar:
       *drm_format = DRM_FORMAT_NV21;
       break;
@@ -202,11 +206,21 @@
       *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
         DRM_FORMAT_MOD_QCOM_DX;
       break;
+    case kFormatYCbCr420P010Tile:
+      *drm_format = DRM_FORMAT_NV12;
+      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_TILE |
+        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 kFormatYCbCr420TP10Tile:
+      *drm_format = DRM_FORMAT_NV12;
+      *drm_format_modifier = DRM_FORMAT_MOD_QCOM_TILE |
+        DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_TIGHT;
+      break;
     case kFormatYCbCr422H2V1SemiPlanar:
       *drm_format = DRM_FORMAT_NV16;
       break;
@@ -257,6 +271,11 @@
     }
 
     MapBufferToFbId(input_buffer);
+
+    if (hw_rotator_session->mode == kRotatorInline && hw_rotate_info->valid &&
+        hw_rotator_session->output_buffer.planes[0].fd >= 0) {
+      MapBufferToFbId(&hw_rotator_session->output_buffer);
+    }
   }
 }
 
@@ -708,7 +727,7 @@
   return kErrorNone;
 }
 
-DisplayError HWDeviceDRM::PowerOn() {
+DisplayError HWDeviceDRM::PowerOn(int *release_fence) {
   DTRACE_SCOPED();
   if (!drm_atomic_intf_) {
     DLOGE("DRM Atomic Interface is null!");
@@ -726,6 +745,7 @@
     DLOGE("Failed with error: %d", ret);
     return kErrorHardware;
   }
+  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, release_fence);
 
   return kErrorNone;
 }
@@ -748,7 +768,7 @@
   return kErrorNone;
 }
 
-DisplayError HWDeviceDRM::Doze() {
+DisplayError HWDeviceDRM::Doze(int *release_fence) {
   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::DOZE);
@@ -758,10 +778,12 @@
     return kErrorHardware;
   }
 
+  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, release_fence);
+
   return kErrorNone;
 }
 
-DisplayError HWDeviceDRM::DozeSuspend() {
+DisplayError HWDeviceDRM::DozeSuspend(int *release_fence) {
   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,
@@ -772,6 +794,8 @@
     return kErrorHardware;
   }
 
+  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, release_fence);
+
   return kErrorNone;
 }
 
@@ -859,11 +883,19 @@
         if (hw_rotator_session->mode == kRotatorInline && hw_rotate_info->valid) {
           SetRect(hw_rotate_info->dst_roi, &rot_dst);
           drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION_DST_RECT, pipe_id, rot_dst);
+          if (hw_rotator_session->output_buffer.planes[0].fd >= 0) {
+            uint32_t rot_fb_id = registry_.GetFbId(hw_rotator_session->output_buffer.planes[0].fd);
+            if (rot_fb_id) {
+              drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROT_FB_ID, pipe_id, rot_fb_id);
+            }
+          }
         }
         DRMRect dst = {};
         SetRect(pipe_info->dst_roi, &dst);
         drm_atomic_intf_->Perform(DRMOps::PLANE_SET_DST_RECT, pipe_id, dst);
-
+        DRMRect excl = {};
+        SetRect(pipe_info->excl_rect, &excl);
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_EXCL_RECT, pipe_id, excl);
         uint32_t rot_bit_mask = 0;
         SetRotation(layer.transform, hw_rotator_session->mode, &rot_bit_mask);
         drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION, pipe_id, rot_bit_mask);
@@ -918,14 +950,17 @@
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_LLCC_IB, token_.crtc_id, qos_data.llcc_ib_bps);
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DRAM_AB, token_.crtc_id, qos_data.dram_ab_bps);
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DRAM_IB, token_.crtc_id, qos_data.dram_ib_bps);
+  drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ROT_PREFILL_BW, token_.crtc_id,
+                            qos_data.rot_prefill_bw_bps);
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ROT_CLK, token_.crtc_id, qos_data.rot_clock_hz);
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_SECURITY_LEVEL, token_.crtc_id, crtc_security_level);
 
-  DLOGI_IF(kTagDriverConfig, "System Clock=%d Hz, Core: AB=%llu Bps, IB=%llu Bps, " \
-           "LLCC: AB=%llu Bps, IB=%llu Bps, DRAM AB=%llu Bps, IB=%llu Bps Rot Clock=%d",
+  DLOGI_IF(kTagDriverConfig, "%s::%s System Clock=%d Hz, Core: AB=%llu Bps, IB=%llu Bps, " \
+           "LLCC: AB=%llu Bps, IB=%llu Bps, DRAM AB=%llu Bps, IB=%llu Bps, "\
+           "Rot: Bw=%llu Bps, Clock=%d Hz", validate ? "Validate" : "Commit", device_name_,
            qos_data.clock_hz, qos_data.core_ab_bps, qos_data.core_ib_bps, qos_data.llcc_ab_bps,
            qos_data.llcc_ib_bps, qos_data.dram_ab_bps, qos_data.dram_ib_bps,
-           qos_data.rot_clock_hz);
+           qos_data.rot_prefill_bw_bps, qos_data.rot_clock_hz);
 
   // Set refresh rate
   if (vrefresh_) {
@@ -1248,8 +1283,8 @@
     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);
+
+    drm_mgr_intf_->GetCrtcPPInfo(token_.crtc_id, &info);
     vers->version[i] = HWColorManagerDrm::GetFeatureVersion(info);
   }
   return kErrorNone;
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index b08c0e6..3ecc9a0 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -67,10 +67,10 @@
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
-  virtual DisplayError PowerOn();
+  virtual DisplayError PowerOn(int *release_fence);
   virtual DisplayError PowerOff();
-  virtual DisplayError Doze();
-  virtual DisplayError DozeSuspend();
+  virtual DisplayError Doze(int *release_fence);
+  virtual DisplayError DozeSuspend(int *release_fence);
   virtual DisplayError Standby();
   virtual DisplayError Validate(HWLayers *hw_layers);
   virtual DisplayError Commit(HWLayers *hw_layers);
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index 5c69ed7..ae3c424 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -119,6 +119,17 @@
   return sdm_version;
 }
 
+static InlineRotationVersion GetInRotVersion(sde_drm::InlineRotationVersion drm_version) {
+  switch (drm_version) {
+    case sde_drm::InlineRotationVersion::V1:
+      return InlineRotationVersion::kInlineRotationV1;
+    case sde_drm::InlineRotationVersion::V1p1:
+      return InlineRotationVersion::kInlineRotationV1p1;
+    default:
+      return kInlineRotationNone;
+  }
+}
+
 HWResourceInfo *HWInfoDRM::hw_resource_ = nullptr;
 
 HWInfoDRM::HWInfoDRM() {
@@ -283,8 +294,9 @@
   hw_resource->has_qseed3 = (info.qseed_version == sde_drm::QSEEDVersion::V3);
   hw_resource->num_blending_stages = info.max_blend_stages;
   hw_resource->num_solidfill_stages = info.max_solidfill_stages;
-  hw_resource->smart_dma_rev = (info.smart_dma_rev == sde_drm::SmartDMARevision::V2) ?
-    SmartDMARevision::V2 : SmartDMARevision::V1;
+  hw_resource->smart_dma_rev = (info.smart_dma_rev == sde_drm::SmartDMARevision::V2p5) ?
+    SmartDMARevision::V2p5 : ((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;
@@ -403,17 +415,20 @@
           name.c_str(), pipe_obj.first, pipe_obj.second.master_plane_id);
     hw_resource->hw_pipes.push_back(std::move(pipe_caps));
   }
+  hw_resource->has_excl_rect = planes[0].second.has_excl_rect;
 }
 
 void HWInfoDRM::PopulatePipeCaps(const sde_drm::DRMPlaneTypeInfo &info,
                                     HWResourceInfo *hw_resource) {
   hw_resource->max_pipe_width = info.max_linewidth;
+  hw_resource->max_scaler_pipe_width = info.max_scaler_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;
   hw_resource->cache_size = info.cache_size;
   hw_resource->pipe_qseed3_version = GetQseedStepVersion(info.qseed3_version);
+  hw_resource->inrot_version = GetInRotVersion(info.inrot_version);
 }
 
 void HWInfoDRM::PopulateSupportedFmts(HWSubBlockType sub_blk_type,
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index f1d0d80..a43ac2c 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -164,11 +164,11 @@
   return kErrorNone;
 }
 
-DisplayError HWTVDRM::Doze() {
+DisplayError HWTVDRM::Doze(int *release_fence) {
   return kErrorNone;
 }
 
-DisplayError HWTVDRM::DozeSuspend() {
+DisplayError HWTVDRM::DozeSuspend(int *release_fence) {
   return kErrorNone;
 }
 
diff --git a/sdm/libs/core/drm/hw_tv_drm.h b/sdm/libs/core/drm/hw_tv_drm.h
index 5661bc2..a87f33d 100644
--- a/sdm/libs/core/drm/hw_tv_drm.h
+++ b/sdm/libs/core/drm/hw_tv_drm.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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:
@@ -43,8 +43,8 @@
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
   virtual DisplayError PowerOff();
-  virtual DisplayError Doze();
-  virtual DisplayError DozeSuspend();
+  virtual DisplayError Doze(int *release_fence);
+  virtual DisplayError DozeSuspend(int *release_fence);
   virtual DisplayError Standby();
   virtual DisplayError Commit(HWLayers *hw_layers);
   virtual void PopulateHWPanelInfo();
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 2c529ae..8dddc51 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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
@@ -62,6 +62,13 @@
 
 namespace sdm {
 
+#ifndef MDP_CSC_ITU_R_2020
+#define MDP_CSC_ITU_R_2020 (MDP_CSC_ITU_R_709 + 1)
+#endif
+#ifndef MDP_CSC_ITU_R_2020_FR
+#define MDP_CSC_ITU_R_2020_FR (MDP_CSC_ITU_R_2020 + 1)
+#endif
+
 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) {
@@ -155,7 +162,7 @@
   return kErrorNone;
 }
 
-DisplayError HWDevice::PowerOn() {
+DisplayError HWDevice::PowerOn(int *release_fence) {
   DTRACE_SCOPED();
 
   if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
@@ -174,11 +181,11 @@
   return kErrorNone;
 }
 
-DisplayError HWDevice::Doze() {
+DisplayError HWDevice::Doze(int *release_fence) {
   return kErrorNone;
 }
 
-DisplayError HWDevice::DozeSuspend() {
+DisplayError HWDevice::DozeSuspend(int *release_fence) {
   return kErrorNone;
 }
 
@@ -1100,12 +1107,10 @@
   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;
   }
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index f32c5bd..353cce5 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -70,10 +70,10 @@
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
-  virtual DisplayError PowerOn();
+  virtual DisplayError PowerOn(int *release_fence);
   virtual DisplayError PowerOff();
-  virtual DisplayError Doze();
-  virtual DisplayError DozeSuspend();
+  virtual DisplayError Doze(int *release_fence);
+  virtual DisplayError DozeSuspend(int *release_fence);
   virtual DisplayError Standby();
   virtual DisplayError Validate(HWLayers *hw_layers);
   virtual DisplayError Commit(HWLayers *hw_layers);
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index 5ee8121..3f3c28e 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015 - 2018, 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
@@ -344,7 +344,7 @@
   return kErrorNone;
 }
 
-DisplayError HWPrimary::Doze() {
+DisplayError HWPrimary::Doze(int *release_fence) {
   if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_NORMAL) < 0) {
     IOCTL_LOGE(FB_BLANK_NORMAL, device_type_);
     return kErrorHardware;
@@ -353,7 +353,7 @@
   return kErrorNone;
 }
 
-DisplayError HWPrimary::DozeSuspend() {
+DisplayError HWPrimary::DozeSuspend(int *release_fence) {
   if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_VSYNC_SUSPEND) < 0) {
     IOCTL_LOGE(FB_BLANK_VSYNC_SUSPEND, device_type_);
     return kErrorHardware;
diff --git a/sdm/libs/core/fb/hw_primary.h b/sdm/libs/core/fb/hw_primary.h
index 69b5445..c6ca5a9 100644
--- a/sdm/libs/core/fb/hw_primary.h
+++ b/sdm/libs/core/fb/hw_primary.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015-2016, 2018 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:
@@ -46,8 +46,8 @@
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
   virtual DisplayError PowerOff();
-  virtual DisplayError Doze();
-  virtual DisplayError DozeSuspend();
+  virtual DisplayError Doze(int *release_fence);
+  virtual DisplayError DozeSuspend(int *release_fence);
   virtual DisplayError Validate(HWLayers *hw_layers);
   virtual DisplayError Commit(HWLayers *hw_layers);
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index 9bb825e..483a4df 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -85,10 +85,10 @@
   virtual DisplayError SetDisplayAttributes(uint32_t index) = 0;
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes) = 0;
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index) = 0;
-  virtual DisplayError PowerOn() = 0;
+  virtual DisplayError PowerOn(int *release_fence) = 0;
   virtual DisplayError PowerOff() = 0;
-  virtual DisplayError Doze() = 0;
-  virtual DisplayError DozeSuspend() = 0;
+  virtual DisplayError Doze(int *release_fence) = 0;
+  virtual DisplayError DozeSuspend(int *release_fence) = 0;
   virtual DisplayError Standby() = 0;
   virtual DisplayError Validate(HWLayers *hw_layers) = 0;
   virtual DisplayError Commit(HWLayers *hw_layers) = 0;
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index f8909f4..cce2cec 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2016, 2018, 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:
@@ -465,11 +465,16 @@
                                         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;
+  uint32_t max_pipe_width = hw_res_info_.max_pipe_width;
+  uint32_t src_width = (uint32_t)(src_rect.right - src_rect.left);
+  uint32_t dst_width = (uint32_t)(dst_rect.right - dst_rect.left);
+
+  if (src_width != dst_width) {
+    max_pipe_width =  hw_res_info_.max_scaler_pipe_width;
+  }
 
   // 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)) {
+  if ((src_width > max_pipe_width) || (dst_width > 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;
diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk
index bd33aff..79f32e2 100644
--- a/sdm/libs/hwc2/Android.mk
+++ b/sdm/libs/hwc2/Android.mk
@@ -9,6 +9,7 @@
 LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes)
+LOCAL_C_INCLUDES              += $(kernel_includes)
 LOCAL_HEADER_LIBRARIES        := display_headers
 
 LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
diff --git a/sdm/libs/hwc2/display_null.cpp b/sdm/libs/hwc2/display_null.cpp
index 16f4da6..99cd017 100644
--- a/sdm/libs/hwc2/display_null.cpp
+++ b/sdm/libs/hwc2/display_null.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -33,7 +33,100 @@
 
 namespace sdm {
 
-DisplayError DisplayNull::Commit(LayerStack *layer_stack) {
+DisplayError DisplayNull::Init() {
+  default_variable_config_.vsync_period_ns = 16600000;
+  default_variable_config_.x_pixels = 1080;
+  default_variable_config_.y_pixels = 1920;
+  default_variable_config_.x_dpi = 300;
+  default_variable_config_.y_dpi = 300;
+  default_variable_config_.fps = 60;
+  default_variable_config_.is_yuv = false;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayNull::GetMixerResolution(uint32_t *width, uint32_t *height) {
+  if (!width || !height) {
+    return kErrorParameters;
+  }
+
+  *width = default_variable_config_.x_pixels;
+  *height = default_variable_config_.y_pixels;
+  return kErrorNone;
+}
+
+DisplayError DisplayNull::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+  if (!variable_info) {
+    return kErrorParameters;
+  }
+
+  *variable_info = default_variable_config_;
+  return kErrorNone;
+}
+
+DisplayError DisplayNull::GetConfig(uint32_t index, DisplayConfigVariableInfo *disp_attr) {
+  if (!disp_attr) {
+    return kErrorParameters;
+  }
+
+  *disp_attr = default_variable_config_;
+  return kErrorNone;
+}
+
+DisplayError DisplayNull::GetConfig(DisplayConfigFixedInfo *fixed_info) {
+  if (!fixed_info) {
+    return kErrorParameters;
+  }
+
+  *fixed_info = default_fixed_config_;
+  return kErrorNone;
+}
+
+DisplayError DisplayNull::GetRefreshRateRange(uint32_t *min_refresh_rate,
+                                              uint32_t *max_refresh_rate) {
+  if (!min_refresh_rate || !max_refresh_rate) {
+    return kErrorParameters;
+  }
+
+  *min_refresh_rate = 60;
+  *max_refresh_rate = 60;
+  return kErrorNone;
+}
+
+DisplayError DisplayNull::GetActiveConfig(uint32_t *config) {
+  if (!config) {
+    return kErrorParameters;
+  }
+
+  *config = 0;
+  return kErrorNone;
+}
+
+DisplayError DisplayNull::GetNumVariableInfoConfigs(uint32_t *count) {
+  if (!count) {
+    return kErrorParameters;
+  }
+
+  *count = 1;
+  return kErrorNone;
+}
+
+DisplayError DisplayNull::Prepare(LayerStack *layer_stack) {
+  if (!layer_stack) {
+    return kErrorParameters;
+  }
+
+  for (auto layer : layer_stack->layers) {
+    layer->composition = kCompositionGPU;
+  }
+  return kErrorNone;
+}
+
+DisplayError DisplayNullExternal::Commit(LayerStack *layer_stack) {
+  if (!layer_stack) {
+    return kErrorParameters;
+  }
+
   for (Layer *layer : layer_stack->layers) {
     if (layer->composition != kCompositionGPUTarget) {
       layer->composition = kCompositionSDE;
@@ -41,26 +134,34 @@
     }
   }
   layer_stack->retire_fence_fd = -1;
-
   return kErrorNone;
 }
 
-DisplayError DisplayNull::GetDisplayState(DisplayState *state) {
+DisplayError DisplayNullExternal::GetDisplayState(DisplayState *state) {
+  if (!state) {
+    return kErrorParameters;
+  }
+
   *state = state_;
   return kErrorNone;
 }
 
-DisplayError DisplayNull::SetDisplayState(DisplayState state) {
+DisplayError DisplayNullExternal::SetDisplayState(DisplayState state, int *release_fence) {
   state_ = state;
   return kErrorNone;
 }
 
-DisplayError DisplayNull::SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) {
+DisplayError DisplayNullExternal::SetFrameBufferConfig(const DisplayConfigVariableInfo
+                                                       &variable_info) {
   fb_config_ = variable_info;
   return kErrorNone;
 }
 
-DisplayError DisplayNull::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+DisplayError DisplayNullExternal::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+  if (!variable_info) {
+    return kErrorParameters;
+  }
+
   *variable_info = fb_config_;
   return kErrorNone;
 }
diff --git a/sdm/libs/hwc2/display_null.h b/sdm/libs/hwc2/display_null.h
index f6c0dda..01f5909 100644
--- a/sdm/libs/hwc2/display_null.h
+++ b/sdm/libs/hwc2/display_null.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -36,35 +36,32 @@
 
 namespace sdm {
 
-#define MAKE_NO_OP(virtual_method_name) \
-      virtual DisplayError virtual_method_name { return kErrorNone; }
+#define MAKE_NO_OP(virtual_method_signature) \
+      virtual DisplayError virtual_method_signature { return kErrorNone; }
 
 class DisplayNull : public DisplayInterface {
  public:
   virtual ~DisplayNull() { }
-  virtual DisplayError Commit(LayerStack *layer_stack);
-  virtual DisplayError GetDisplayState(DisplayState *state);
-  virtual DisplayError SetDisplayState(DisplayState state);
-  virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
+  virtual DisplayError Init();
+  virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+
   virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
+  virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *disp_attr);
+  virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
+  virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
+  virtual DisplayError GetActiveConfig(uint32_t *config);
+  virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
+  virtual DisplayError Prepare(LayerStack *layer_stack);
+  virtual bool IsPrimaryDisplay() { return true; }
   virtual bool IsUnderscanSupported() { return true; }
   virtual void SetIdleTimeoutMs(uint32_t active_ms) { }
-  virtual bool IsPrimaryDisplay() { return true; }
+  virtual std::string Dump() { return ""; }
 
-  void SetActive(bool active) {
-    active_ = active;
-  }
-
-  bool IsActive() {
-    return active_;
-  }
-
-  MAKE_NO_OP(Prepare(LayerStack *))
+  MAKE_NO_OP(Commit(LayerStack *))
+  MAKE_NO_OP(GetDisplayState(DisplayState *))
+  MAKE_NO_OP(SetDisplayState(DisplayState, int*))
+  MAKE_NO_OP(SetFrameBufferConfig(const DisplayConfigVariableInfo &))
   MAKE_NO_OP(Flush())
-  MAKE_NO_OP(GetNumVariableInfoConfigs(uint32_t *))
-  MAKE_NO_OP(GetConfig(uint32_t, DisplayConfigVariableInfo *))
-  MAKE_NO_OP(GetConfig(DisplayConfigFixedInfo *))
-  MAKE_NO_OP(GetActiveConfig(uint32_t *))
   MAKE_NO_OP(GetVSyncState(bool *))
   MAKE_NO_OP(SetActiveConfig(uint32_t))
   MAKE_NO_OP(SetActiveConfig(DisplayConfigVariableInfo *))
@@ -86,18 +83,29 @@
   MAKE_NO_OP(GetDefaultColorMode(std::string *))
   MAKE_NO_OP(ApplyDefaultDisplayMode())
   MAKE_NO_OP(SetCursorPosition(int, int))
-  MAKE_NO_OP(GetRefreshRateRange(uint32_t *, uint32_t *))
   MAKE_NO_OP(SetRefreshRate(uint32_t, bool))
   MAKE_NO_OP(GetPanelBrightness(int *))
   MAKE_NO_OP(SetVSyncState(bool))
   MAKE_NO_OP(SetMixerResolution(uint32_t, uint32_t))
-  MAKE_NO_OP(GetMixerResolution(uint32_t *, uint32_t *))
   MAKE_NO_OP(SetDetailEnhancerData(const DisplayDetailEnhancerData &))
   MAKE_NO_OP(GetDisplayPort(DisplayPort *))
   MAKE_NO_OP(SetCompositionState(LayerComposition, bool))
   MAKE_NO_OP(GetClientTargetSupport(uint32_t, uint32_t, LayerBufferFormat,
                                     const ColorMetaData &))
-  std::string Dump() { return ""; }
+
+  DisplayConfigVariableInfo default_variable_config_ = {};
+  DisplayConfigFixedInfo default_fixed_config_ = {};
+};
+
+class DisplayNullExternal : public DisplayNull {
+ public:
+  virtual DisplayError Commit(LayerStack *layer_stack);
+  virtual DisplayError GetDisplayState(DisplayState *state);
+  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
+  virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
+  virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
+  void SetActive(bool active) { active_ = active; }
+  bool IsActive() { return active_; }
 
  private:
   bool active_ = false;
diff --git a/sdm/libs/hwc2/hwc_buffer_allocator.cpp b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
index e9839b9..84fbd80 100644
--- a/sdm/libs/hwc2/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015-2018, 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
@@ -293,6 +293,7 @@
       *target = HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS;
       break;
     case kFormatYCbCr420SPVenusUbwc:
+    case kFormatYCbCr420SPVenusTile:
       *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
       *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
       break;
@@ -330,10 +331,12 @@
       *target = HAL_PIXEL_FORMAT_YCbCr_420_P010;
       break;
     case kFormatYCbCr420TP10Ubwc:
+    case kFormatYCbCr420TP10Tile:
       *target = HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC;
       *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
       break;
     case kFormatYCbCr420P010Ubwc:
+    case kFormatYCbCr420P010Tile:
       *target = HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC;
       *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
       break;
diff --git a/sdm/libs/hwc2/hwc_buffer_sync_handler.cpp b/sdm/libs/hwc2/hwc_buffer_sync_handler.cpp
index 784e91b..f2dacb2 100644
--- a/sdm/libs/hwc2/hwc_buffer_sync_handler.cpp
+++ b/sdm/libs/hwc2/hwc_buffer_sync_handler.cpp
@@ -27,6 +27,7 @@
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#include <errno.h>
 #include <sync/sync.h>
 #include <utils/constants.h>
 #include <utils/debug.h>
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 0ce1f1e..340a7ac 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -360,11 +360,23 @@
 }
 
 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;
+  DisplayError error = kErrorNone;
+
+  HWCDebugHandler::Get()->GetProperty("sdm.debug.enable_null_display", &null_display_mode_);
+
+  if (null_display_mode_) {
+    DisplayNull *disp_null = new DisplayNull();
+    disp_null->Init();
+    use_metadata_refresh_rate_ = false;
+    display_intf_ = disp_null;
+    ALOGI("Enabling null display mode for display type %d", type_);
+  } else {
+    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;
+    }
   }
 
   validated_ = false;
@@ -405,10 +417,15 @@
 }
 
 int HWCDisplay::Deinit() {
-  DisplayError error = core_intf_->DestroyDisplay(display_intf_);
-  if (error != kErrorNone) {
-    DLOGE("Display destroy failed. Error = %d", error);
-    return -EINVAL;
+  if (null_display_mode_) {
+    delete static_cast<DisplayNull *>(display_intf_);
+    display_intf_ = nullptr;
+  } else {
+    DisplayError error = core_intf_->DestroyDisplay(display_intf_);
+    if (error != kErrorNone) {
+      DLOGE("Display destroy failed. Error = %d", error);
+      return -EINVAL;
+    }
   }
 
   delete client_target_;
@@ -421,8 +438,10 @@
     delete color_mode_;
   }
 
-  delete tone_mapper_;
-  tone_mapper_ = nullptr;
+  if (tone_mapper_) {
+    delete tone_mapper_;
+    tone_mapper_ = nullptr;
+  }
 
   return 0;
 }
@@ -434,6 +453,8 @@
   *out_layer_id = layer->GetId();
   geometry_changes_ |= GeometryChanges::kAdded;
   validated_ = false;
+  layer_stack_invalid_ = true;
+
   return HWC2::Error::None;
 }
 
@@ -466,6 +487,8 @@
 
   geometry_changes_ |= GeometryChanges::kRemoved;
   validated_ = false;
+  layer_stack_invalid_ = true;
+
   return HWC2::Error::None;
 }
 
@@ -633,6 +656,8 @@
   }
   // set secure display
   SetSecureDisplay(secure_display_active);
+
+  layer_stack_invalid_ = false;
 }
 
 void HWCDisplay::BuildSolidFillStack() {
@@ -742,9 +767,10 @@
     default:
       return HWC2::Error::BadParameter;
   }
+  int release_fence = -1;
 
   ATRACE_INT("SetPowerMode ", state);
-  DisplayError error = display_intf_->SetDisplayState(state);
+  DisplayError error = display_intf_->SetDisplayState(state, &release_fence);
   validated_ = false;
 
   if (error == kErrorNone) {
@@ -758,6 +784,20 @@
     return HWC2::Error::BadParameter;
   }
 
+  if (release_fence >= 0) {
+    for (auto hwc_layer : layer_set_) {
+      auto fence = hwc_layer->PopBackReleaseFence();
+      auto merged_fence = -1;
+      if (fence >= 0) {
+        merged_fence = sync_merge("sync_merge", release_fence, fence);
+        ::close(fence);
+      } else {
+        merged_fence = ::dup(release_fence);
+      }
+      hwc_layer->PushBackReleaseFence(merged_fence);
+    }
+    ::close(release_fence);
+  }
   return HWC2::Error::None;
 }
 
@@ -1014,7 +1054,10 @@
 HWC2::Error HWCDisplay::PrepareLayerStack(uint32_t *out_num_types, uint32_t *out_num_requests) {
   layer_changes_.clear();
   layer_requests_.clear();
+  has_client_composition_ = false;
+
   if (shutdown_pending_) {
+    validated_ = false;
     return HWC2::Error::BadDisplay;
   }
 
@@ -1029,9 +1072,8 @@
         // so that previous buffer and fences are released, and override the error.
         flush_ = true;
       }
+      validated_ = false;
       return HWC2::Error::BadDisplay;
-    } else {
-      validated_ = true;
     }
   } else {
     // Skip is not set
@@ -1055,6 +1097,9 @@
     // Set SDM composition to HWC2 type in HWCLayer
     hwc_layer->SetComposition(composition);
     HWC2::Composition device_composition  = hwc_layer->GetDeviceSelectedCompositionType();
+    if (device_composition == HWC2::Composition::Client) {
+      has_client_composition_ = true;
+    }
     // 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) {
@@ -1062,15 +1107,14 @@
     }
     hwc_layer->ResetValidation();
   }
+
   client_target_->ResetValidation();
   *out_num_types = UINT32(layer_changes_.size());
   *out_num_requests = UINT32(layer_requests_.size());
-  skip_validate_ = false;
-  if (*out_num_types > 0) {
-    return HWC2::Error::HasChanges;
-  } else {
-    return HWC2::Error::None;
-  }
+  validate_state_ = kNormalValidate;
+  validated_ = true;
+
+  return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
 }
 
 HWC2::Error HWCDisplay::AcceptDisplayChanges() {
@@ -1129,7 +1173,7 @@
     for (uint32_t i = 0; i < *out_num_elements; i++, it++) {
       auto hwc_layer = *it;
       out_layers[i] = hwc_layer->GetId();
-      out_fences[i] = hwc_layer->PopReleaseFence();
+      out_fences[i] = hwc_layer->PopFrontReleaseFence();
     }
   } else {
     *out_num_elements = UINT32(layer_set_.size());
@@ -1214,10 +1258,6 @@
 
 
 HWC2::Error HWCDisplay::CommitLayerStack(void) {
-  if (skip_validate_ && !CanSkipValidate()) {
-    validated_ = false;
-  }
-
   if (!validated_) {
     DLOGV_IF(kTagClient, "Display %d is not validated", id_);
     return HWC2::Error::NotValidated;
@@ -1263,7 +1303,7 @@
     }
   }
 
-  skip_validate_ = true;
+  validate_state_ = kSkipValidate;
   return HWC2::Error::None;
 }
 
@@ -1300,15 +1340,15 @@
       if (swap_interval_zero_ || layer->flags.single_buffer) {
         close(layer_buffer->release_fence_fd);
       } else if (layer->composition != kCompositionGPU) {
-        hwc_layer->PushReleaseFence(layer_buffer->release_fence_fd);
+        hwc_layer->PushBackReleaseFence(layer_buffer->release_fence_fd);
       } else {
-        hwc_layer->PushReleaseFence(-1);
+        hwc_layer->PushBackReleaseFence(-1);
       }
     } else {
       // In case of flush, we don't return an error to f/w, so it will get a release fence out of
       // the hwc_layer's release fence queue. We should push a -1 to preserve release fence
       // circulation semantics.
-      hwc_layer->PushReleaseFence(-1);
+      hwc_layer->PushBackReleaseFence(-1);
     }
 
     layer_buffer->release_fence_fd = -1;
@@ -1761,7 +1801,7 @@
   if (hwc_layer->GetDeviceSelectedCompositionType() != HWC2::Composition::Cursor) {
     return HWC2::Error::None;
   }
-  if (!skip_validate_ && validated_) {
+  if ((validate_state_ != kSkipValidate) && validated_) {
     // the device is currently in the middle of the validate/present sequence,
     // cannot set the Position(as per HWC2 spec)
     return HWC2::Error::NotValidated;
@@ -2040,6 +2080,11 @@
        << std::endl;
   }
 
+  if (layer_stack_invalid_) {
+    os << "\n Layers added or removed but not reflected to SDM's layer stack yet\n";
+    return os.str();
+  }
+
   if (color_mode_) {
     os << "\n----------Color Modes---------\n";
     color_mode_->Dump(&os);
@@ -2056,8 +2101,7 @@
 }
 
 bool HWCDisplay::CanSkipValidate() {
-  if (solid_fill_enable_) {
-    DLOGV_IF(kTagClient, "Solid fill is enabled. Returning false.");
+  if (!validated_ || solid_fill_enable_) {
     return false;
   }
 
@@ -2091,4 +2135,12 @@
   return true;
 }
 
+HWC2::Error HWCDisplay::GetValidateDisplayOutput(uint32_t *out_num_types,
+                                                 uint32_t *out_num_requests) {
+  *out_num_types = UINT32(layer_changes_.size());
+  *out_num_requests = UINT32(layer_requests_.size());
+
+  return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index c251944..212de7f 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -36,6 +36,7 @@
 #include "hwc_buffer_allocator.h"
 #include "hwc_callbacks.h"
 #include "hwc_layers.h"
+#include "display_null.h"
 
 namespace sdm {
 
@@ -102,6 +103,12 @@
     kDisplayStatusResume,
   };
 
+  enum DisplayValidateState {
+    kNormalValidate,
+    kInternalValidate,
+    kSkipValidate,
+  };
+
   virtual ~HWCDisplay() {}
   virtual int Init();
   virtual int Deinit();
@@ -164,6 +171,11 @@
   HWCLayer *GetHWCLayer(hwc2_layer_t layer_id);
   void ResetValidation() { validated_ = false; }
   uint32_t GetGeometryChanges() { return geometry_changes_; }
+  bool CanSkipValidate();
+  bool HasClientComposition() { return has_client_composition_; }
+  bool IsSkipValidateState() { return (validate_state_ == kSkipValidate); }
+  bool IsInternalValidateState() { return (validated_ && (validate_state_ == kInternalValidate)); }
+  void SetValidationState(DisplayValidateState state) { validate_state_ = state; }
 
   // HWC2 APIs
   virtual HWC2::Error AcceptDisplayChanges(void);
@@ -219,6 +231,7 @@
     validated_ = false;
     return HWC2::Error::None;
   }
+  virtual HWC2::Error GetValidateDisplayOutput(uint32_t *out_num_types, uint32_t *out_num_requests);
 
  protected:
   // Maximum number of layers supported by display manager.
@@ -257,6 +270,7 @@
   };
 
   bool validated_ = false;
+  bool layer_stack_invalid_ = true;
   CoreInterface *core_intf_ = nullptr;
   HWCCallbacks *callbacks_  = nullptr;
   HWCBufferAllocator *buffer_allocator_ = NULL;
@@ -302,12 +316,13 @@
 
  private:
   void DumpInputBuffers(void);
-  bool CanSkipValidate();
   qService::QService *qservice_ = NULL;
   DisplayClass display_class_;
   uint32_t geometry_changes_ = GeometryChanges::kNone;
-  bool skip_validate_ = false;
   bool animating_ = false;
+  int null_display_mode_ = 0;
+  bool has_client_composition_ = false;
+  DisplayValidateState validate_state_ = kNormalValidate;
 };
 
 inline int HWCDisplay::Perform(uint32_t operation, ...) {
diff --git a/sdm/libs/hwc2/hwc_display_external.cpp b/sdm/libs/hwc2/hwc_display_external.cpp
index 2bc2d18..675484b 100644
--- a/sdm/libs/hwc2/hwc_display_external.cpp
+++ b/sdm/libs/hwc2/hwc_display_external.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2018, 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
@@ -230,9 +230,12 @@
         DLOGW("Set frame buffer config failed. Error = %d", error);
         return -1;
       }
-
+      int release_fence = -1;
       display_null_.GetDisplayState(&state);
-      display_intf_->SetDisplayState(state);
+      display_intf_->SetDisplayState(state, &release_fence);
+      if (release_fence >= 0) {
+        ::close(release_fence);
+      }
       validated_ = false;
 
       SetVsyncEnabled(HWC2::Vsync::Enable);
@@ -244,10 +247,14 @@
     }
   } else {
     if (!display_null_.IsActive()) {
+      int release_fence = -1;
       // Preserve required attributes of HDMI display that surfaceflinger sees.
       // Restore HDMI attributes when display is reconnected.
       display_intf_->GetDisplayState(&state);
-      display_null_.SetDisplayState(state);
+      display_null_.SetDisplayState(state, &release_fence);
+      if (release_fence >= 0) {
+        ::close(release_fence);
+      }
 
       error = display_intf_->GetFrameBufferConfig(&fb_config);
       if (error != kErrorNone) {
diff --git a/sdm/libs/hwc2/hwc_display_external.h b/sdm/libs/hwc2/hwc_display_external.h
index fbee6a3..75e9387 100644
--- a/sdm/libs/hwc2/hwc_display_external.h
+++ b/sdm/libs/hwc2/hwc_display_external.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, 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
@@ -58,7 +58,7 @@
   static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
                                      uint32_t *virtual_width, uint32_t *virtual_height);
 
-  DisplayNull display_null_;
+  DisplayNullExternal display_null_;
   int underscan_width_ = 0;
   int underscan_height_ = 0;
 };
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp
index 1f2fdf6..21c958d 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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
@@ -475,13 +475,17 @@
 }
 
 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 {
+  if (dump_frame_count_) {
+    int ret = 0;
+    if (output_buffer_.release_fence_fd >= 0) {
+      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));
+      }
+    }
+    if (ret >= 0) {
       DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence_fd);
     }
   }
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index d611352..1193ec4 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -174,14 +174,14 @@
   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);
+  release_fences_.push_back(-1);
 }
 
 HWCLayer::~HWCLayer() {
   // Close any fences left for this layer
   while (!release_fences_.empty()) {
     ::close(release_fences_.front());
-    release_fences_.pop();
+    release_fences_.pop_front();
   }
   if (layer_) {
     if (layer_->input_buffer.acquire_fence_fd >= 0) {
@@ -892,14 +892,28 @@
 
   return;
 }
-void HWCLayer::PushReleaseFence(int32_t fence) {
-  release_fences_.push(fence);
+
+void HWCLayer::PushBackReleaseFence(int32_t fence) {
+  release_fences_.push_back(fence);
 }
-int32_t HWCLayer::PopReleaseFence(void) {
+
+int32_t HWCLayer::PopBackReleaseFence() {
   if (release_fences_.empty())
     return -1;
+
+  auto fence = release_fences_.back();
+  release_fences_.pop_back();
+
+  return fence;
+}
+
+int32_t HWCLayer::PopFrontReleaseFence() {
+  if (release_fences_.empty())
+    return -1;
+
   auto fence = release_fences_.front();
-  release_fences_.pop();
+  release_fences_.pop_front();
+
   return fence;
 }
 
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index ed03c50..a7d7f01 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -32,7 +32,7 @@
 #undef HWC2_INCLUDE_STRINGIFICATION
 #undef HWC2_USE_CPP11
 #include <map>
-#include <queue>
+#include <deque>
 #include <set>
 #include "core/buffer_allocator.h"
 #include "hwc_buffer_allocator.h"
@@ -88,8 +88,9 @@
   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);
+  void PushBackReleaseFence(int32_t fence);
+  int32_t PopBackReleaseFence(void);
+  int32_t PopFrontReleaseFence(void);
   bool ValidateAndSetCSC();
   bool SupportLocalConversion(ColorPrimaries working_primaries);
   void ResetValidation() { needs_validate_ = false; }
@@ -104,7 +105,7 @@
   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_;
+  std::deque<int32_t> release_fences_;
   HWCBufferAllocator *buffer_allocator_ = NULL;
   int32_t dataspace_ =  HAL_DATASPACE_UNKNOWN;
   LayerTransform layer_transform_ = {};
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 36b55d0..4302bd9 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -72,6 +72,7 @@
 
 static HWCUEvent g_hwc_uevent_;
 Locker HWCSession::locker_[HWC_NUM_DISPLAY_TYPES];
+static const int kSolidFillDelay = 100 * 1000;
 
 void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) {
   const char *uevent_thread_name = "HWC_UeventThread";
@@ -160,35 +161,44 @@
 
   StartServices();
 
+  HWCDebugHandler::Get()->GetProperty("sdm.debug.enable_null_display", &null_display_mode_);
+
   DisplayError error = buffer_allocator_.Init();
   if (error != kErrorNone) {
-    ALOGE("%s::%s: Buffer allocaor initialization failed. Error = %d",
+    ALOGE("%s::%s: Buffer allocator initialization failed. Error = %d",
           __CLASS__, __FUNCTION__, error);
     return -EINVAL;
   }
 
-  g_hwc_uevent_.Register(this);
+  HWDisplayInterfaceInfo hw_disp_info = {};
+  if (null_display_mode_) {
+    hw_disp_info.type = kPrimary;
+    hw_disp_info.is_connected = true;
+  } else {
+    g_hwc_uevent_.Register(this);
 
-  error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
-                                    &buffer_sync_handler_, &socket_handler_, &core_intf_);
-  if (error != kErrorNone) {
-    buffer_allocator_.Deinit();
-    ALOGE("%s::%s: Display core initialization failed. Error = %d", __CLASS__, __FUNCTION__, error);
-    return -EINVAL;
+    error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
+                                      &buffer_sync_handler_, &socket_handler_, &core_intf_);
+
+    if (error != kErrorNone) {
+      buffer_allocator_.Deinit();
+      ALOGE("%s::%s: Display core initialization failed. Error = %d", __CLASS__, __FUNCTION__,
+            error);
+      return -EINVAL;
+    }
+
+    error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
+
+    if (error != kErrorNone) {
+      g_hwc_uevent_.Register(nullptr);
+      CoreInterface::DestroyCore();
+      buffer_allocator_.Deinit();
+      DLOGE("Primary display type not recognized. Error = %d", error);
+      return -EINVAL;
+    }
   }
 
-
   // If HDMI display is primary display, defer display creation until hotplug event is received.
-  HWDisplayInterfaceInfo hw_disp_info = {};
-  error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
-  if (error != kErrorNone) {
-    g_hwc_uevent_.Register(nullptr);
-    CoreInterface::DestroyCore();
-    buffer_allocator_.Deinit();
-    DLOGE("Primary display type not recognized. Error = %d", error);
-    return -EINVAL;
-  }
-
   if (hw_disp_info.type == kHDMI) {
     status = 0;
     hdmi_is_primary_ = true;
@@ -246,11 +256,13 @@
     color_mgr_->DestroyColorManager();
   }
 
-  g_hwc_uevent_.Register(nullptr);
+  if (!null_display_mode_) {
+    g_hwc_uevent_.Register(nullptr);
 
-  DisplayError error = CoreInterface::DestroyCore();
-  if (error != kErrorNone) {
-    ALOGE("Display core de-initialization failed. Error = %d", error);
+    DisplayError error = CoreInterface::DestroyCore();
+    if (error != kErrorNone) {
+      ALOGE("Display core de-initialization failed. Error = %d", error);
+    }
   }
 
   return 0;
@@ -542,7 +554,7 @@
 
     // TODO(user): Handle virtual display/HDMI concurrency
     if (hwc_session->hwc_display_[display]) {
-      status = hwc_session->hwc_display_[display]->Present(out_retire_fence);
+      status = hwc_session->PresentDisplayInternal(display, out_retire_fence);
     }
   }
 
@@ -782,24 +794,7 @@
   {
     SEQUENCE_ENTRY_SCOPE_LOCK(locker_[display]);
     if (hwc_session->hwc_display_[display]) {
-      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->Refresh(display);
-          hwc_session->need_invalidate_ = false;
-        }
-
-        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);
+      status = hwc_session->ValidateDisplayInternal(display, out_num_types, out_num_requests);
     }
   }
 
@@ -1530,14 +1525,22 @@
           ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
           break;
         case kApplySolidFill:
-          ret = color_mgr_->SetSolidFill(pending_action.params,
+          {
+            SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+            ret = color_mgr_->SetSolidFill(pending_action.params,
                                             true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+          }
           Refresh(HWC_DISPLAY_PRIMARY);
+          usleep(kSolidFillDelay);
           break;
         case kDisableSolidFill:
-          ret = color_mgr_->SetSolidFill(pending_action.params,
+          {
+            SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+            ret = color_mgr_->SetSolidFill(pending_action.params,
                                             false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+          }
           Refresh(HWC_DISPLAY_PRIMARY);
+          usleep(kSolidFillDelay);
           break;
         case kSetPanelBrightness:
           brightness_value = reinterpret_cast<int32_t *>(resp_payload.payload);
@@ -1880,4 +1883,48 @@
 }
 #endif
 
+HWC2::Error HWCSession::ValidateDisplayInternal(hwc2_display_t display, uint32_t *out_num_types,
+                                                uint32_t *out_num_requests) {
+  HWCDisplay *hwc_display = hwc_display_[display];
+  if (hwc_display->IsInternalValidateState()) {
+    // Internal Validation has already been done on display, get the Output params.
+    return hwc_display->GetValidateDisplayOutput(out_num_types, out_num_requests);
+  }
+
+  if (display == HWC_DISPLAY_PRIMARY) {
+    // TODO(user): This can be moved to HWCDisplayPrimary
+    if (reset_panel_) {
+      DLOGW("panel is in bad state, resetting the panel");
+      ResetPanel();
+    }
+
+    if (need_invalidate_) {
+      Refresh(display);
+      need_invalidate_ = false;
+    }
+
+    if (color_mgr_) {
+      color_mgr_->SetColorModeDetailEnhancer(hwc_display_[display]);
+    }
+  }
+
+  return hwc_display->Validate(out_num_types, out_num_requests);
+}
+
+HWC2::Error HWCSession::PresentDisplayInternal(hwc2_display_t display, int32_t *out_retire_fence) {
+  HWCDisplay *hwc_display = hwc_display_[display];
+  // If display is in Skip-Validate state and Validate cannot be skipped, do Internal
+  // Validation to optimize for the frames which don't require the Client composition.
+  if (hwc_display->IsSkipValidateState() && !hwc_display->CanSkipValidate()) {
+    uint32_t out_num_types = 0, out_num_requests = 0;
+    HWC2::Error error = ValidateDisplayInternal(display, &out_num_types, &out_num_requests);
+    if ((error != HWC2::Error::None) || hwc_display->HasClientComposition()) {
+      hwc_display->SetValidationState(HWCDisplay::kInternalValidate);
+      return HWC2::Error::NotValidated;
+    }
+  }
+
+  return hwc_display->Present(out_retire_fence);
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 8d25989..4bd7b00 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -247,6 +247,9 @@
 
   void Refresh(hwc2_display_t display);
   void HotPlug(hwc2_display_t display, HWC2::Connection state);
+  HWC2::Error ValidateDisplayInternal(hwc2_display_t display, uint32_t *out_num_types,
+                                      uint32_t *out_num_requests);
+  HWC2::Error PresentDisplayInternal(hwc2_display_t display, int32_t *out_retire_fence);
 
   CoreInterface *core_intf_ = nullptr;
   HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {nullptr};
@@ -267,6 +270,7 @@
   Locker callbacks_lock_;
   int hpd_bpp_ = 0;
   int hpd_pattern_ = 0;
+  int null_display_mode_ = 0;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 6984711..f91b8f1 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -452,6 +452,10 @@
 Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
 
+  if (null_display_mode_) {
+    return 0;
+  }
+
   if (!core_intf_) {
     DLOGW("core_intf_ not initialized.");
     return -ENOENT;
diff --git a/sdm/libs/hwc2/hwc_tonemapper.cpp b/sdm/libs/hwc2/hwc_tonemapper.cpp
index 26caec9..2ae1afc 100644
--- a/sdm/libs/hwc2/hwc_tonemapper.cpp
+++ b/sdm/libs/hwc2/hwc_tonemapper.cpp
@@ -146,22 +146,22 @@
   release_fence_fd_[current_buffer_index_] = dup(fd);
 }
 
-void ToneMapSession::SetToneMapConfig(Layer *layer) {
+void ToneMapSession::SetToneMapConfig(Layer *layer, PrimariesTransfer blend_cs) {
   // 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_.blend_cs = blend_cs;
   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) {
+bool ToneMapSession::IsSameToneMapConfig(Layer *layer, PrimariesTransfer blend_cs) {
   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) &&
+          (blend_cs == tone_map_config_.blend_cs) &&
           (buffer.color_metadata.transfer == tone_map_config_.transfer) &&
           (layer->request.flags.secure == tone_map_config_.secure) &&
           (layer->request.format == tone_map_config_.format) &&
@@ -197,11 +197,11 @@
             return 0;
           }
         }
-        error = AcquireToneMapSession(layer, &session_index);
+        error = AcquireToneMapSession(layer, &session_index, layer_stack->blend_cs);
         fb_session_index_ = INT(session_index);
         break;
       default:
-        error = AcquireToneMapSession(layer, &session_index);
+        error = AcquireToneMapSession(layer, &session_index, layer_stack->blend_cs);
         break;
       }
 
@@ -331,7 +331,8 @@
   CloseFd(acquire_fd);
 }
 
-DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index) {
+DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index,
+                                                  PrimariesTransfer blend_cs) {
   // 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.
@@ -344,7 +345,7 @@
   // 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)) {
+    if (!tonemap_session->acquired_ && tonemap_session->IsSameToneMapConfig(layer, blend_cs)) {
       tonemap_session->current_buffer_index_ = (tonemap_session->current_buffer_index_ + 1) %
                                                 ToneMapSession::kNumIntermediateBuffers;
       tonemap_session->acquired_ = true;
@@ -358,7 +359,7 @@
     return kErrorMemory;
   }
 
-  session->SetToneMapConfig(layer);
+  session->SetToneMapConfig(layer, blend_cs);
 
   ToneMapGetInstanceContext ctx;
   ctx.layer = layer;
diff --git a/sdm/libs/hwc2/hwc_tonemapper.h b/sdm/libs/hwc2/hwc_tonemapper.h
index 8bef3b1..bc564eb 100644
--- a/sdm/libs/hwc2/hwc_tonemapper.h
+++ b/sdm/libs/hwc2/hwc_tonemapper.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2016 - 2018, 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
@@ -64,7 +64,7 @@
 
 struct ToneMapConfig {
   int type = 0;
-  ColorPrimaries colorPrimaries = ColorPrimaries_Max;
+  PrimariesTransfer blend_cs = {};
   GammaTransfer transfer = Transfer_Max;
   LayerBufferFormat format = kFormatRGBA8888;
   bool secure = false;
@@ -78,8 +78,8 @@
   void FreeIntermediateBuffers();
   void UpdateBuffer(int acquire_fence, LayerBuffer *buffer);
   void SetReleaseFence(int fd);
-  void SetToneMapConfig(Layer *layer);
-  bool IsSameToneMapConfig(Layer *layer);
+  void SetToneMapConfig(Layer *layer, PrimariesTransfer blend_cs);
+  bool IsSameToneMapConfig(Layer *layer, PrimariesTransfer blend_cs);
 
   // TaskHandler methods implementation.
   virtual void OnTask(const ToneMapTaskCode &task_code,
@@ -110,7 +110,7 @@
 
  private:
   void ToneMap(Layer *layer, ToneMapSession *session);
-  DisplayError AcquireToneMapSession(Layer *layer, uint32_t *session_index);
+  DisplayError AcquireToneMapSession(Layer *layer, uint32_t *sess_idx, PrimariesTransfer blend_cs);
   void DumpToneMapOutput(ToneMapSession *session, int *acquire_fence);
 
   std::vector<ToneMapSession*> tone_map_sessions_;
diff --git a/sdm/libs/utils/formats.cpp b/sdm/libs/utils/formats.cpp
index 42dfea9..bb6ee94 100644
--- a/sdm/libs/utils/formats.cpp
+++ b/sdm/libs/utils/formats.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2016-2018, 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
@@ -100,6 +100,7 @@
   case kFormatYCbCr422H2V1SemiPlanar:   return "Y_CBCR_422_H2V1";
   case kFormatYCrCb422H2V1SemiPlanar:   return "Y_CRCB_422_H2V2";
   case kFormatYCbCr420SPVenusUbwc:      return "Y_CBCR_420_VENUS_UBWC";
+  case kFormatYCbCr420SPVenusTile:      return "Y_CBCR_420_VENUS_TILED";
   case kFormatYCbCr422H2V1Packed:       return "YCBYCR_422_H2V1";
   case kFormatCbYCrY422H2V1Packed:      return "CBYCRY_422_H2V1";
   case kFormatRGBA1010102:              return "RGBA_1010102";
@@ -116,6 +117,8 @@
   case kFormatYCbCr420TP10Ubwc:         return "Y_CBCR_420_TP10_UBWC";
   case kFormatYCbCr420P010Ubwc:         return "Y_CBCR_420_P010_UBWC";
   case kFormatYCbCr420P010Venus:        return "Y_CBCR_420_P010_VENUS";
+  case kFormatYCbCr420TP10Tile:         return "Y_CBCR_420_TP10_TILED";
+  case kFormatYCbCr420P010Tile:         return "Y_CBCR_420_P010_TILED";
   default:                              return "UNKNOWN";
   }
 }
@@ -123,7 +126,11 @@
 BufferLayout GetBufferLayout(LayerBufferFormat format) {
   switch (format) {
   case kFormatYCbCr420TP10Ubwc:
+  case kFormatYCbCr420TP10Tile:
     return kTPTiled;
+  case kFormatYCbCr420SPVenusTile:
+  case kFormatYCbCr420P010Tile:
+    return kUBWC;
   default:
     return (IsUBWCFormat(format) ? kUBWC : kLinear);
   }
@@ -156,6 +163,7 @@
     case kFormatYCbCr420P010:
     case kFormatYCbCr420P010Ubwc:
     case kFormatYCbCr420P010Venus:
+    case kFormatYCbCr420P010Tile:
       return 3.0f;
     case kFormatRGB565:
     case kFormatBGR565:
@@ -167,6 +175,7 @@
     case kFormatYCrCb422H2V1SemiPlanar:
     case kFormatYCbCr422H2V1SemiPlanar:
     case kFormatYCbCr420TP10Ubwc:
+    case kFormatYCbCr420TP10Tile:
     case kFormatYCbCr422H1V2SemiPlanar:
     case kFormatYCrCb422H1V2SemiPlanar:
       return 2.0f;
@@ -178,6 +187,7 @@
     case kFormatYCbCr420SemiPlanarVenus:
     case kFormatYCrCb420SemiPlanarVenus:
     case kFormatYCbCr420SPVenusUbwc:
+    case kFormatYCbCr420SPVenusTile:
       return 1.5f;
     default:
       return 0.0f;
@@ -189,18 +199,21 @@
 DisplayError GetBufferFormatTileSize(LayerBufferFormat format, FormatTileSize *tile_size) {
   switch (format) {
   case kFormatYCbCr420SPVenusUbwc:
+  case kFormatYCbCr420SPVenusTile:
     tile_size->tile_width = 32;
     tile_size->tile_height = 8;
     tile_size->uv_tile_width = 16;
     tile_size->uv_tile_height = 8;
     break;
   case kFormatYCbCr420TP10Ubwc:
+  case kFormatYCbCr420TP10Tile:
     tile_size->tile_width = 48;
     tile_size->tile_height = 4;
     tile_size->uv_tile_width = 24;
     tile_size->uv_tile_height = 4;
     break;
   case kFormatYCbCr420P010Ubwc:
+  case kFormatYCbCr420P010Tile:
     tile_size->tile_width = 32;
     tile_size->tile_height = 4;
     tile_size->uv_tile_width = 16;
@@ -212,5 +225,25 @@
   return kErrorNone;
 }
 
+bool HasAlphaChannel(LayerBufferFormat format) {
+  switch (format) {
+  case kFormatARGB8888:
+  case kFormatRGBA8888:
+  case kFormatBGRA8888:
+  case kFormatRGBA5551:
+  case kFormatRGBA4444:
+  case kFormatRGBA8888Ubwc:
+  case kFormatRGBA1010102:
+  case kFormatARGB2101010:
+  case kFormatBGRA1010102:
+  case kFormatABGR2101010:
+  case kFormatRGBA1010102Ubwc:
+    return true;
+  default:
+    return false;
+  }
+}
+
+
 }  // namespace sdm
 
diff --git a/sdm/libs/utils/rect.cpp b/sdm/libs/utils/rect.cpp
index a830542..e121b58 100644
--- a/sdm/libs/utils/rect.cpp
+++ b/sdm/libs/utils/rect.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015-2018, 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
@@ -98,6 +98,47 @@
   return res;
 }
 
+// Is rect2 completely inside rect1?
+bool Contains(const LayerRect &rect1, const LayerRect &rect2) {
+  if (!IsValid(rect1) || !IsValid(rect2)) {
+    return false;
+  }
+  return (rect1.top <= rect2.top && rect1.bottom >= rect2.bottom &&
+          rect1.left <= rect2.left && rect1.right >= rect2.right);
+}
+
+// subtracts 2 rects iff result of subtraction is 2 rects.
+void Subtract(const LayerRect &rect1, const LayerRect &rect2, LayerRect *res) {
+  if (!res) {
+    return;
+  }
+  if (!IsValid(rect1) || !IsValid(rect2)) {
+    return;
+  }
+
+  if (rect1.left != rect2.left || rect1.right != rect2.right) {
+    return;
+  }
+  res[0].left = rect1.left;
+  res[0].right = rect1.right;
+  if (rect1.top < rect2.top) {
+    res[0].top = rect1.top;
+    res[0].bottom = rect2.top;
+  } else {
+    res[0].top = rect2.top;
+    res[0].bottom = rect1.top;
+  }
+  res[1].left = rect1.left;
+  res[1].right = rect1.right;
+  if (rect1.bottom < rect2.bottom) {
+    res[1].top = rect1.bottom;
+    res[1].bottom = rect2.bottom;
+  } else {
+    res[1].top = rect2.bottom;
+    res[1].bottom = rect1.bottom;
+  }
+}
+
 // 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;