Merge "sdm: Update perflock enum for display layer hint"
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index a7e00c5..1b59fde 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -105,6 +105,7 @@
     LINK_adreno_isMacroTilingSupportedByGpu = NULL;
     LINK_adreno_compute_compressedfmt_aligned_width_and_height = NULL;
     LINK_adreno_isUBWCSupportedByGpu = NULL;
+    LINK_adreno_get_gpu_pixel_alignment = NULL;
 
     libadreno_utils = ::dlopen("libadreno_utils.so", RTLD_NOW);
     if (libadreno_utils) {
@@ -119,6 +120,8 @@
                         "compute_compressedfmt_aligned_width_and_height");
         *(void **)&LINK_adreno_isUBWCSupportedByGpu =
                 ::dlsym(libadreno_utils, "isUBWCSupportedByGpu");
+        *(void **)&LINK_adreno_get_gpu_pixel_alignment =
+                ::dlsym(libadreno_utils, "get_gpu_pixel_alignment");
     }
 
     // Check if the overriding property debug.gralloc.gfx_ubwc_disable
@@ -149,6 +152,52 @@
     return 0;
 }
 
+void AdrenoMemInfo::getAlignedWidthAndHeight(const private_handle_t *hnd, int& aligned_w,
+                          int& aligned_h) {
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+    if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+        int w = metadata->bufferDim.sliceWidth;
+        int h = metadata->bufferDim.sliceHeight;
+        int f = hnd->format;
+        int usage = 0;
+
+        if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+            usage = GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+        }
+
+        getAlignedWidthAndHeight(w, h, f, usage, aligned_w, aligned_h);
+    } else {
+        aligned_w = hnd->width;
+        aligned_h = hnd->height;
+    }
+
+}
+
+bool isUncompressedRgbFormat(int format)
+{
+    bool is_rgb_format = false;
+
+    switch (format)
+    {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGB_888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444:
+        case HAL_PIXEL_FORMAT_R_8:
+        case HAL_PIXEL_FORMAT_RG_88:
+        case HAL_PIXEL_FORMAT_BGRX_8888:    // Intentional fallthrough
+            is_rgb_format = true;
+            break;
+        default:
+            break;
+    }
+
+    return is_rgb_format;
+}
 
 void AdrenoMemInfo::getAlignedWidthAndHeight(int width, int height, int format,
                             int usage, int& aligned_w, int& aligned_h)
@@ -156,10 +205,9 @@
     bool ubwc_enabled = isUBwcEnabled(format, usage);
 
     // Currently surface padding is only computed for RGB* surfaces.
-    if (format <= HAL_PIXEL_FORMAT_BGRA_8888) {
+    if (isUncompressedRgbFormat(format) == true) {
         int tileEnabled = ubwc_enabled || isMacroTileEnabled(format, usage);
-        AdrenoMemInfo::getInstance().getGpuAlignedWidthHeight(width,
-            height, format, tileEnabled, aligned_w, aligned_h);
+        getGpuAlignedWidthHeight(width, height, format, tileEnabled, aligned_w, aligned_h);
         return;
     }
 
@@ -170,11 +218,18 @@
 
     aligned_w = width;
     aligned_h = height;
+    int alignment = 32;
     switch (format)
     {
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+            if (LINK_adreno_get_gpu_pixel_alignment) {
+              alignment = LINK_adreno_get_gpu_pixel_alignment();
+            }
+            aligned_w = ALIGN(width, alignment);
+            break;
         case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
-            aligned_w = ALIGN(width, 32);
+            aligned_w = ALIGN(width, alignment);
             break;
         case HAL_PIXEL_FORMAT_RAW16:
             aligned_w = ALIGN(width, 16);
@@ -185,7 +240,6 @@
         case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
             aligned_w = ALIGN(width, 128);
             break;
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
         case HAL_PIXEL_FORMAT_YV12:
         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
         case HAL_PIXEL_FORMAT_YCrCb_422_SP:
@@ -277,6 +331,7 @@
             bpp = 3;
             break;
         case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
         case HAL_PIXEL_FORMAT_RGBA_5551:
         case HAL_PIXEL_FORMAT_RGBA_4444:
             bpp = 2;
@@ -329,6 +384,8 @@
             return ADRENO_PIXELFORMAT_R8G8B8X8;
         case HAL_PIXEL_FORMAT_RGB_565:
             return ADRENO_PIXELFORMAT_B5G6R5;
+        case HAL_PIXEL_FORMAT_BGR_565:
+            return ADRENO_PIXELFORMAT_R5G6B5;
         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
             return ADRENO_PIXELFORMAT_NV12;
         case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
@@ -458,6 +515,7 @@
             case  HAL_PIXEL_FORMAT_RGBX_8888:
             case  HAL_PIXEL_FORMAT_BGRA_8888:
             case  HAL_PIXEL_FORMAT_RGB_565:
+            case  HAL_PIXEL_FORMAT_BGR_565:
                 {
                     tileEnabled = true;
                     // check the usage flags
@@ -494,6 +552,7 @@
             size = alignedw * alignedh * 3;
             break;
         case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
         case HAL_PIXEL_FORMAT_RGBA_5551:
         case HAL_PIXEL_FORMAT_RGBA_4444:
         case HAL_PIXEL_FORMAT_RAW16:
@@ -649,6 +708,7 @@
     int width = hnd->width;
     int height = hnd->height;
     int format = hnd->format;
+
     unsigned int ystride, cstride;
     unsigned int alignment = 4096;
 
@@ -662,8 +722,14 @@
 
     // Check metadata if the geometry has been updated.
     if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+        int usage = 0;
+
+        if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+            usage = GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+        }
+
         AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(metadata->bufferDim.sliceWidth,
-                   metadata->bufferDim.sliceHeight, format, 0, width, height);
+                   metadata->bufferDim.sliceHeight, format, usage, width, height);
     }
 
     // Get the chroma offsets from the handle width/height. We take advantage
@@ -819,7 +885,7 @@
     // Existing HAL formats with UBWC support
     switch(format)
     {
-        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_RGBX_8888:
         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
@@ -836,12 +902,18 @@
     if (isUBwcFormat(format))
         return true;
 
-    // Allow UBWC, if client sets UBWC gralloc usage flag & GPU supports format.
-    if ((usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) && isUBwcSupported(format) &&
-        AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format)) {
+    // Allow UBWC, if an OpenGL client sets UBWC usage flag and GPU plus MDP
+    // support the format. OR if a non-OpenGL client like Rotator, sets UBWC
+    // usage flag and MDP supports the format.
+    if ((usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) && isUBwcSupported(format)) {
+        bool enable = true;
+        // Query GPU for UBWC only if buffer is intended to be used by GPU.
+        if (usage & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER)) {
+            enable = AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format);
+        }
         // Allow UBWC, only if CPU usage flags are not set
-        if (!(usage & (GRALLOC_USAGE_SW_READ_MASK |
-                      GRALLOC_USAGE_SW_WRITE_MASK))) {
+        if (enable && !(usage & (GRALLOC_USAGE_SW_READ_MASK |
+            GRALLOC_USAGE_SW_WRITE_MASK))) {
             return true;
         }
     }
@@ -922,7 +994,7 @@
 
     unsigned int size = 0;
     switch (format) {
-        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
             size = alignedw * alignedh * 2;
             size += getUBwcMetaBufferSize(width, height, 2);
             break;
@@ -948,7 +1020,7 @@
     int err = 0;
 
     // This api is for RGB* formats
-    if (hnd->format > HAL_PIXEL_FORMAT_BGRA_8888) {
+    if (!isUncompressedRgbFormat(hnd->format)) {
         return -EINVAL;
     }
 
@@ -960,7 +1032,7 @@
 
     unsigned int meta_size = 0;
     switch (hnd->format) {
-        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
             meta_size = getUBwcMetaBufferSize(hnd->width, hnd->height, 2);
             break;
         case HAL_PIXEL_FORMAT_RGBA_8888:
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 98ae919..4b62c9c 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -95,6 +95,9 @@
         if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY) {
             flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
         }
+        if (usage & GRALLOC_USAGE_PRIVATE_INTERNAL_ONLY) {
+            flags |= private_handle_t::PRIV_FLAGS_INTERNAL_ONLY;
+        }
 
         ColorSpace_t colorSpace = ITU_R_601;
         flags |= private_handle_t::PRIV_FLAGS_ITU_R_601;
@@ -145,8 +148,7 @@
             flags |= private_handle_t::PRIV_FLAGS_TILE_RENDERED;
         }
 
-        if (isUBwcEnabled(format, usage) &&
-            AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format)) {
+        if (isUBwcEnabled(format, usage)) {
             flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
         }
 
@@ -189,12 +191,9 @@
 {
     *bufferType = BUFFER_TYPE_VIDEO;
 
-    if (inputFormat <= HAL_PIXEL_FORMAT_BGRA_8888) {
+    if (isUncompressedRgbFormat(inputFormat) == TRUE) {
         // RGB formats
         *bufferType = BUFFER_TYPE_UI;
-    } else if ((inputFormat == HAL_PIXEL_FORMAT_R_8) ||
-               (inputFormat == HAL_PIXEL_FORMAT_RG_88)) {
-        *bufferType = BUFFER_TYPE_UI;
     }
 }
 
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index e27203a..1b8d9b4 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -76,6 +76,9 @@
 // To query if UBWC is enabled, based on format and usage flags
 bool isUBwcEnabled(int format, int usage);
 
+// Function to check if the format is an uncompressed RGB format
+bool isUncompressedRgbFormat(int format);
+
 /*****************************************************************************/
 
 class Locker {
@@ -120,6 +123,14 @@
                             int usage, int& aligned_w, int& aligned_h);
 
     /*
+     * Function to compute aligned width and aligned height based on
+     * private handle
+     *
+     * @return aligned width, aligned height
+     */
+    void getAlignedWidthAndHeight(const private_handle_t *hnd, int& aligned_w, int& aligned_h);
+
+    /*
      * Function to compute the adreno aligned width and aligned height
      * based on the width and format.
      *
@@ -183,5 +194,7 @@
                                                 int *bpp);
 
         int (*LINK_adreno_isUBWCSupportedByGpu) (ADRENOPIXELFORMAT format);
+
+        unsigned int (*LINK_adreno_get_gpu_pixel_alignment) ();
 };
 #endif /* GR_H_ */
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 2601953..1438546 100755
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -105,6 +105,7 @@
 #define HAL_PIXEL_FORMAT_BGRX_8888               0x112
 #define HAL_PIXEL_FORMAT_NV21_ZSL                0x113
 #define HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS      0x114
+#define HAL_PIXEL_FORMAT_BGR_565                 0x115
 #define HAL_PIXEL_FORMAT_INTERLACE               0x180
 
 //v4l2_fourcc('Y', 'U', 'Y', 'L'). 24 bpp YUYV 4:2:2 10 bit per component
@@ -172,6 +173,7 @@
             PRIV_FLAGS_USES_ION           = 0x00000008,
             PRIV_FLAGS_USES_ASHMEM        = 0x00000010,
             PRIV_FLAGS_NEEDS_FLUSH        = 0x00000020,
+            PRIV_FLAGS_INTERNAL_ONLY      = 0x00000040,
             PRIV_FLAGS_NON_CPU_WRITER     = 0x00000080,
             PRIV_FLAGS_NONCONTIGUOUS_MEM  = 0x00000100,
             PRIV_FLAGS_CACHED             = 0x00000200,
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 3cfdc55..a5d3e69 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -344,36 +344,33 @@
 
         case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE:
             {
-                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                const private_handle_t* hnd =  va_arg(args, private_handle_t*);
                 int *stride = va_arg(args, int *);
                 if (private_handle_t::validate(hnd)) {
                     return res;
                 }
-                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
-                if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
-                    *stride = metadata->bufferDim.sliceWidth;
-                } else {
-                    *stride = hnd->width;
-                }
+
+                int alignedw = 0, alignedh = 0;
+                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
+                *stride = alignedw;
+
                 res = 0;
             } break;
 
         case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE:
             {
-                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                const private_handle_t* hnd =  va_arg(args, private_handle_t*);
                 int *stride = va_arg(args, int *);
                 int *height = va_arg(args, int *);
                 if (private_handle_t::validate(hnd)) {
                     return res;
                 }
-                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
-                if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
-                    *stride = metadata->bufferDim.sliceWidth;
-                    *height = metadata->bufferDim.sliceHeight;
-                } else {
-                    *stride = hnd->width;
-                    *height = hnd->height;
-                }
+
+                int alignedw = 0, alignedh = 0;
+                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
+                *stride = alignedw;
+                *height = alignedh;
+
                 res = 0;
             } break;
 
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 8f77c66..43887e0 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -300,6 +300,41 @@
     return err;
 }
 
+int setPanelBrightness(int level) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+
+    if(binder != NULL) {
+        inParcel.writeInt32(level);
+        status_t err = binder->dispatch(IQService::SET_PANEL_BRIGHTNESS,
+                &inParcel, &outParcel);
+        if(err) {
+            ALOGE("%s() failed with err %d", __FUNCTION__, err);
+        }
+    }
+    return err;
+}
+
+int getPanelBrightness() {
+    int panel_brightness = -1;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+
+    if(binder != NULL) {
+        status_t err = binder->dispatch(IQService::GET_PANEL_BRIGHTNESS,
+                &inParcel, &outParcel);
+        if(!err) {
+            panel_brightness = outParcel.readInt32();
+            ALOGI("%s() Current panel brightness value %d", __FUNCTION__,
+                    panel_brightness);
+        } else {
+            ALOGE("%s() failed with err %d", __FUNCTION__, err);
+        }
+    }
+    return panel_brightness;
+}
+
 }// namespace
 
 // ----------------------------------------------------------------------------
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index b6232ca..8e3fa78 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -145,6 +145,12 @@
 // Only HDMI display is supported as dpy for now
 int minHdcpEncryptionLevelChanged(int dpy);
 
+// Sets the panel brightness of the primary display
+int setPanelBrightness(int level);
+
+// Retrieves the current panel brightness value
+int getPanelBrightness();
+
 }; //namespace
 
 #endif
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index 2aa4a31..952952d 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -61,7 +61,7 @@
     data->operation |= paramType;
     switch (paramType) {
         case PP_PARAM_HSIC:
-            memcpy((void *)&data->hsicData, param, sizeof(HSICData_t));
+            data->hsicData = *((HSICData_t *)param);
             break;
         case PP_PARAM_SHARPNESS:
             data->sharpness = *((int32_t *)param);
@@ -76,13 +76,13 @@
             memcpy((void *)&data->igcData, param, sizeof(IGCData_t));
             break;
         case PP_PARAM_SHARP2:
-            memcpy((void *)&data->Sharp2Data, param, sizeof(Sharp2Data_t));
+            data->Sharp2Data = *((Sharp2Data_t *)param);
             break;
         case PP_PARAM_TIMESTAMP:
             data->timestamp = *((int64_t *)param);
             break;
         case UPDATE_BUFFER_GEOMETRY:
-            memcpy((void *)&data->bufferDim, param, sizeof(BufferDim_t));
+            data->bufferDim = *((BufferDim_t *)param);
             break;
         case UPDATE_REFRESH_RATE:
             data->refreshrate = *((uint32_t *)param);
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index df8e235..422ddb2 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -40,8 +40,8 @@
     DECLARE_META_INTERFACE(QService);
     enum {
         COMMAND_LIST_START = android::IBinder::FIRST_CALL_TRANSACTION,
-        SECURING = 2,           // Hardware securing start/end notification
-        UNSECURING = 3,         // Hardware unsecuring start/end notification
+        GET_PANEL_BRIGHTNESS = 2, // Provides ability to set the panel brightness
+        SET_PANEL_BRIGHTNESS = 3, // Provides ability to get the panel brightness
         CONNECT_HWC_CLIENT = 4, // Connect to qservice
         SCREEN_REFRESH = 5,     // Refresh screen through SF invalidate
         EXTERNAL_ORIENTATION = 6,// Set external orientation
@@ -59,7 +59,7 @@
         /* Enable/Disable/Set refresh rate dynamically */
         CONFIGURE_DYN_REFRESH_RATE = 18,
         CONTROL_PARTIAL_UPDATE = 19,   // Provides ability to enable/disable partial update
-        CONTROL_BACKLIGHT = 20, // Provides ability to control backlight
+        TOGGLE_SCREEN_UPDATES = 20, // Provides ability to set the panel brightness
         SET_FRAME_DUMP_CONFIG = 21,  // Provides ability to set the frame dump config
         SET_S3D_MODE = 22, // Set the 3D mode as specified in msm_hdmi_modes.h
         CONNECT_HDMI_CLIENT = 23,  // Connect HDMI CEC HAL Client
diff --git a/libqservice/QServiceUtils.h b/libqservice/QServiceUtils.h
index fbad484..73b2b18 100644
--- a/libqservice/QServiceUtils.h
+++ b/libqservice/QServiceUtils.h
@@ -62,21 +62,12 @@
 // ----------------------------------------------------------------------------
 // Convenience wrappers that clients can call
 // ----------------------------------------------------------------------------
-inline android::status_t securing(uint32_t startEnd) {
-    return sendSingleParam(qService::IQService::SECURING, startEnd);
-}
-
-inline android::status_t unsecuring(uint32_t startEnd) {
-    return sendSingleParam(qService::IQService::UNSECURING, startEnd);
-}
-
 inline android::status_t screenRefresh() {
     return sendSingleParam(qService::IQService::SCREEN_REFRESH, 1);
 }
 
-// TODO(user): Need to rename this wrapper name
 inline android::status_t toggleScreenUpdate(uint32_t on) {
-    return sendSingleParam(qService::IQService::CONTROL_BACKLIGHT, on);
+    return sendSingleParam(qService::IQService::TOGGLE_SCREEN_UPDATES, on);
 }
 
 inline android::status_t setExtOrientation(uint32_t orientation) {
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 9edd9c8..01037b4 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -344,6 +344,15 @@
   virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst,
                                       bool rotate90) = 0;
 
+  /*! @brief Method to get the min and max refresh rate of a display.
+
+    @param[out] min and max refresh rate.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate,
+                                           uint32_t *max_refresh_rate) = 0;
+
   /*! @brief Method to set the refresh rate of a display.
 
     @param[in] new refresh rate of the display.
@@ -399,6 +408,14 @@
   */
   virtual DisplayError SetCursorPosition(int x, int y) = 0;
 
+  /*! @brief Method to get the brightness level of the display
+
+    @param[out] level brightness level
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetPanelBrightness(int *level) = 0;
+
  protected:
   virtual ~DisplayInterface() { }
 };
diff --git a/sdm/include/core/layer_buffer.h b/sdm/include/core/layer_buffer.h
index 524a84b..5d48a04 100644
--- a/sdm/include/core/layer_buffer.h
+++ b/sdm/include/core/layer_buffer.h
@@ -54,9 +54,10 @@
   kFormatRGB888,        //!< 8-bits Red, Green, Blue interleaved in RGB order. No Alpha.
   kFormatBGR888,        //!< 8-bits Blue, Green, Red interleaved in BGR order. No Alpha.
   kFormatRGB565,        //!< 5-bit Red, 6-bit Green, 5-bit Blue interleaved in RGB order. No Alpha.
+  kFormatBGR565,        //!< 5-bit Blue, 6-bit Green, 5-bit Red interleaved in BGR order. No Alpha.
   kFormatRGBA8888Ubwc,  //!< UBWC aligned RGBA8888 format
   kFormatRGBX8888Ubwc,  //!< UBWC aligned RGBX8888 format
-  kFormatRGB565Ubwc,    //!< UBWC aligned RGB565 format
+  kFormatBGR565Ubwc,    //!< UBWC aligned BGR565 format
 
   /* All YUV-Planar formats, Any new format will be added towards end of this group to maintain
      backward compatibility.
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 44dd63a..0c1b5f4 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -270,7 +270,6 @@
 
   uint32_t count = 0;              // Total number of layers which need to be set on hardware.
 
-  bool need_sync_handle = false;
   int sync_handle = -1;
 
   LayerRect left_partial_update;   // Left ROI.
diff --git a/sdm/include/utils/rect.h b/sdm/include/utils/rect.h
index 04f3bf3..91d70c2 100644
--- a/sdm/include/utils/rect.h
+++ b/sdm/include/utils/rect.h
@@ -47,9 +47,9 @@
   LayerRect Subtract(const LayerRect &rect1, const LayerRect &rect2);
   LayerRect Reposition(const LayerRect &rect1, const int &x_offset, const int &y_offset);
   void SplitLeftRight(const LayerRect &in_rect, uint32_t split_count, uint32_t align_x,
-                     LayerRect *out_rects);
+                      bool flip_horizontal, LayerRect *out_rects);
   void SplitTopBottom(const LayerRect &in_rect, uint32_t split_count, uint32_t align_y,
-                       LayerRect *out_rects);
+                      bool flip_horizontal, LayerRect *out_rects);
 }  // namespace sdm
 
 #endif  // __RECT_H__
diff --git a/sdm/include/utils/sys.h b/sdm/include/utils/sys.h
index 1c7e415..dc45696 100644
--- a/sdm/include/utils/sys.h
+++ b/sdm/include/utils/sys.h
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <poll.h>
+#include <pthread.h>
 
 namespace sdm {
 
@@ -43,6 +44,8 @@
   typedef FILE* (*fopen)( const char *fname, const char *mode);
   typedef int (*fclose)(FILE* fileptr);
   typedef ssize_t (*getline)(char **lineptr, size_t *linelen, FILE *stream);
+  typedef int (*pthread_cancel)(pthread_t thread);
+  typedef int (*dup)(int fd);
 
   static ioctl ioctl_;
   static open open_;
@@ -53,6 +56,8 @@
   static fopen fopen_;
   static fclose fclose_;
   static getline getline_;
+  static pthread_cancel pthread_cancel_;
+  static dup dup_;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 4cfc2c4..de4b326 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -149,15 +149,39 @@
   return kErrorNone;
 }
 
-void CompManager::ReconfigureDisplay(Handle comp_handle, const HWDisplayAttributes &attributes,
-                                     const HWPanelInfo &hw_panel_info) {
+DisplayError CompManager::ReconfigureDisplay(Handle comp_handle,
+                                             const HWDisplayAttributes &attributes,
+                                             const HWPanelInfo &hw_panel_info) {
   DisplayCompositionContext *display_comp_ctx =
                              reinterpret_cast<DisplayCompositionContext *>(comp_handle);
 
   resource_intf_->ReconfigureDisplay(display_comp_ctx->display_resource_ctx, attributes,
                                      hw_panel_info);
 
-  // TODO(user): Need to reconfigure strategy with updated panel info
+  DisplayError error = kErrorNone;
+  if (display_comp_ctx->strategy) {
+    display_comp_ctx->strategy->Deinit();
+    delete display_comp_ctx->strategy;
+    display_comp_ctx->strategy = NULL;
+  }
+
+  Strategy *&new_strategy = display_comp_ctx->strategy;
+  display_comp_ctx->strategy = new Strategy(extension_intf_, display_comp_ctx->display_type,
+                                            hw_res_info_, hw_panel_info);
+  if (!display_comp_ctx->strategy) {
+    DLOGE("Unable to create strategy.");
+    return kErrorMemory;
+  }
+
+  error = new_strategy->Init();
+  if (error != kErrorNone) {
+    DLOGE("Unable to initialize strategy.");
+    delete display_comp_ctx->strategy;
+    display_comp_ctx->strategy = NULL;
+    return error;
+  }
+
+  return error;
 }
 
 void CompManager::PrepareStrategyConstraints(Handle comp_handle, HWLayers *hw_layers) {
@@ -416,8 +440,8 @@
     return supported;
   }
   Layer &cursor_layer = layer_stack->layers[gpu_index - 1];
-  if (resource_intf_->ValidateCursorConfig(display_resource_ctx, cursor_layer, true) ==
-                                           kErrorNone) {
+  if (cursor_layer.flags.cursor && resource_intf_->ValidateCursorConfig(display_resource_ctx,
+                                   cursor_layer, true) == kErrorNone) {
     supported = true;
   }
 
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index f8175f3..8db045a 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -44,8 +44,8 @@
   DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
                                const HWPanelInfo &hw_panel_info, Handle *res_mgr_hnd);
   DisplayError UnregisterDisplay(Handle res_mgr_hnd);
-  void ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
-                          const HWPanelInfo &hw_panel_info);
+  DisplayError ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
+                                  const HWPanelInfo &hw_panel_info);
   void PrePrepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
@@ -89,8 +89,8 @@
   Locker locker_;
   ResourceInterface *resource_intf_ = NULL;
   ResourceDefault resource_default_;
-  uint64_t registered_displays_ = 0;    // Stores the bit mask of registered displays
-  uint64_t configured_displays_ = 0;    // Stores the bit mask of sucessfully configured displays
+  uint32_t registered_displays_ = 0;    // Stores the bit mask of registered displays
+  uint32_t configured_displays_ = 0;    // Stores the bit mask of sucessfully configured displays
   bool safe_mode_ = false;              // Flag to notify all displays to be in resource crunch
                                         // mode, where strategy manager chooses the best strategy
                                         // that uses optimal number of pipes for each display
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 30aac4e..ad67dd0 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -302,6 +302,8 @@
     return kErrorParameters;
   }
 
+  *enabled = vsync_enable_;
+
   return kErrorNone;
 }
 
@@ -472,7 +474,7 @@
                          num_modes, active_index);
 
   DisplayConfigVariableInfo &info = attrib;
-  DumpImpl::AppendString(buffer, length, "\nres:%u x %u, dpi:%.2f x %.2f, fps:%.2f,"
+  DumpImpl::AppendString(buffer, length, "\nres:%u x %u, dpi:%.2f x %.2f, fps:%u,"
                          "vsync period: %u", info.x_pixels, info.y_pixels, info.x_dpi,
                          info.y_dpi, info.fps, info.vsync_period_ns);
 
@@ -618,9 +620,10 @@
   case kFormatRGB888:                   return "RGB_888";
   case kFormatBGR888:                   return "BGR_888";
   case kFormatRGB565:                   return "RGB_565";
+  case kFormatBGR565:                   return "BGR_565";
   case kFormatRGBA8888Ubwc:             return "RGBA_8888_UBWC";
   case kFormatRGBX8888Ubwc:             return "RGBX_8888_UBWC";
-  case kFormatRGB565Ubwc:               return "RGB_565_UBWC";
+  case kFormatBGR565Ubwc:               return "BGR_565_UBWC";
   case kFormatYCbCr420Planar:           return "Y_CB_CR_420";
   case kFormatYCrCb420Planar:           return "Y_CR_CB_420";
   case kFormatYCrCb420PlanarStride16:   return "Y_CR_CB_420_STRIDE16";
@@ -666,4 +669,26 @@
   return kErrorNone;
 }
 
+DisplayError DisplayBase::GetRefreshRateRange(uint32_t *min_refresh_rate,
+                                              uint32_t *max_refresh_rate) {
+  // The min and max refresh rates will be same when the HWPanelInfo does not contain valid rates.
+  // Usually for secondary displays, command mode panels
+  HWDisplayAttributes display_attributes;
+  uint32_t active_index = 0;
+  hw_intf_->GetActiveConfig(&active_index);
+  DisplayError error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
+  if (error) {
+    return error;
+  }
+
+  *min_refresh_rate = display_attributes.fps;
+  *max_refresh_rate = display_attributes.fps;
+
+  return error;
+}
+
+DisplayError DisplayBase::GetPanelBrightness(int *level) {
+  return kErrorNotSupported;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index dae9074..2f2c072 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -71,6 +71,8 @@
                                             PPPendingParams *pending_action);
   virtual DisplayError ApplyDefaultDisplayMode(void);
   virtual DisplayError SetCursorPosition(int x, int y);
+  virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
+  virtual DisplayError GetPanelBrightness(int *level);
 
  protected:
   // DumpImpl method
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
index 8add374..76deba0 100644
--- a/sdm/libs/core/display_hdmi.cpp
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -155,6 +155,12 @@
   return DisplayBase::IsScalingValid(crop, dst, rotate90);
 }
 
+DisplayError DisplayHDMI::GetRefreshRateRange(uint32_t *min_refresh_rate,
+                                              uint32_t *max_refresh_rate) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
+}
+
 DisplayError DisplayHDMI::SetRefreshRate(uint32_t refresh_rate) {
   SCOPE_LOCK(locker_);
   return kErrorNotSupported;
diff --git a/sdm/libs/core/display_hdmi.h b/sdm/libs/core/display_hdmi.h
index b6f4116..2f50a3d 100644
--- a/sdm/libs/core/display_hdmi.h
+++ b/sdm/libs/core/display_hdmi.h
@@ -55,6 +55,7 @@
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual DisplayError SetDisplayMode(uint32_t mode);
   virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+  virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
   virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
   virtual bool IsUnderscanSupported();
   virtual DisplayError SetPanelBrightness(int level);
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index 8698ab8..1a00da4 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -104,7 +104,7 @@
   hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
 
   if (panel_info != hw_panel_info_) {
-    comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info);
+    error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info);
     hw_panel_info_ = panel_info;
   }
 
@@ -222,8 +222,22 @@
     return error;
   }
 
+  // Disable PU if the previous PU state is on when switching to video mode, and re-enable PU when
+  // switching back to command mode.
+  bool toggle_partial_update = !(hw_display_mode == kModeVideo);
+  if (partial_update_control_) {
+    comp_manager_->ControlPartialUpdate(display_comp_ctx_, toggle_partial_update);
+  }
+
+  if (hw_display_mode == kModeVideo) {
+    hw_intf_->SetIdleTimeoutMs(Debug::GetIdleTimeoutMs());
+  } else if (hw_display_mode == kModeCommand) {
+    hw_intf_->SetIdleTimeoutMs(0);
+  }
+
   return error;
 }
+
 DisplayError DisplayPrimary::SetPanelBrightness(int level) {
   SCOPE_LOCK(locker_);
   return hw_intf_->SetPanelBrightness(level);
@@ -235,21 +249,50 @@
   return DisplayBase::IsScalingValid(crop, dst, rotate90);
 }
 
+DisplayError DisplayPrimary::GetRefreshRateRange(uint32_t *min_refresh_rate,
+                                                 uint32_t *max_refresh_rate) {
+  SCOPE_LOCK(locker_);
+  DisplayError error = kErrorNone;
+
+  if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) {
+    *min_refresh_rate = hw_panel_info_.min_fps;
+    *max_refresh_rate = hw_panel_info_.max_fps;
+  } else {
+    error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
+  }
+
+  return error;
+}
+
 DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate) {
   SCOPE_LOCK(locker_);
 
-  if (!hw_panel_info_.dynamic_fps) {
-    DLOGW("Dynamic fps feature is not supported");
+  if (!hw_panel_info_.dynamic_fps || refresh_rate < hw_panel_info_.min_fps ||
+       refresh_rate > hw_panel_info_.max_fps) {
+    DLOGW("Invalid Request");
     return kErrorNotSupported;
   }
 
-  if (refresh_rate > hw_panel_info_.max_fps) {
-    refresh_rate = hw_panel_info_.max_fps;
-  } else if (refresh_rate < hw_panel_info_.min_fps) {
-    refresh_rate = hw_panel_info_.min_fps;
+  DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
+  if (error != kErrorNone) {
+    return error;
   }
 
-  return hw_intf_->SetRefreshRate(refresh_rate);
+  HWDisplayAttributes display_attributes;
+  uint32_t active_index = 0;
+  error = hw_intf_->GetActiveConfig(&active_index);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info_);
+
+  return kErrorNone;
 }
 
 void DisplayPrimary::AppendDump(char *buffer, uint32_t length) {
@@ -288,5 +331,10 @@
   comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
 }
 
+DisplayError DisplayPrimary::GetPanelBrightness(int *level) {
+  SCOPE_LOCK(locker_);
+  return hw_intf_->GetPanelBrightness(level);
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index 1a61688..900939d 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -55,11 +55,13 @@
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual DisplayError SetDisplayMode(uint32_t mode);
   virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+  virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
   virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
   virtual bool IsUnderscanSupported();
   virtual DisplayError SetPanelBrightness(int level);
   virtual void AppendDump(char *buffer, uint32_t length);
   virtual DisplayError SetCursorPosition(int x, int y);
+  virtual DisplayError GetPanelBrightness(int *level);
 
   // Implement the HWEventHandlers
   virtual DisplayError VSync(int64_t timestamp);
diff --git a/sdm/libs/core/display_virtual.cpp b/sdm/libs/core/display_virtual.cpp
index ea4e829..ff8da68 100644
--- a/sdm/libs/core/display_virtual.cpp
+++ b/sdm/libs/core/display_virtual.cpp
@@ -177,6 +177,12 @@
   return DisplayBase::IsScalingValid(crop, dst, rotate90);
 }
 
+DisplayError DisplayVirtual::GetRefreshRateRange(uint32_t *min_refresh_rate,
+                                                 uint32_t *max_refresh_rate) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
+}
+
 DisplayError DisplayVirtual::SetRefreshRate(uint32_t refresh_rate) {
   SCOPE_LOCK(locker_);
   return kErrorNotSupported;
diff --git a/sdm/libs/core/display_virtual.h b/sdm/libs/core/display_virtual.h
index 10978a7..b26be12 100644
--- a/sdm/libs/core/display_virtual.h
+++ b/sdm/libs/core/display_virtual.h
@@ -56,6 +56,7 @@
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual DisplayError SetDisplayMode(uint32_t mode);
   virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+  virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
   virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
   virtual bool IsUnderscanSupported();
   virtual DisplayError SetPanelBrightness(int level);
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 97aa5c9..3ebd202 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -228,10 +228,8 @@
         mdp_layer.bg_color = layer.solid_fill_color;
 
         if (pipe_info->scale_data.enable_pixel_ext) {
-          if ((mdp_layer.flags & MDP_LAYER_DEINTERLACE) && (layer.transform.rotation == 90.0f)) {
-            mdp_buffer.width = pipe_info->scale_data.src_width;
-          }
           SetHWScaleData(pipe_info->scale_data, mdp_layer_count);
+          mdp_layer.flags |= MDP_LAYER_ENABLE_PIXEL_EXT;
         }
 
         // Send scale data to MDP driver
@@ -275,6 +273,9 @@
     mdp_out_layer_.writeback_ndx = 2;
     mdp_out_layer_.buffer.width = output_buffer->width;
     mdp_out_layer_.buffer.height = output_buffer->height;
+    if (output_buffer->flags.secure) {
+      mdp_out_layer_.flags |= MDP_LAYER_SECURE_SESSION;
+    }
     mdp_out_layer_.buffer.comp_ratio.denom = 1000;
     mdp_out_layer_.buffer.comp_ratio.numer = UINT32(hw_layers->output_compression * 1000);
     SetFormat(output_buffer->format, &mdp_out_layer_.buffer.format);
@@ -432,19 +433,19 @@
       input_buffer = &hw_rotator_session->output_buffer;
     }
 
-    input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+    input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence);
   }
 
-  if (hw_layer_info.need_sync_handle) {
-    hw_layer_info.sync_handle = dup(mdp_commit.release_fence);
-  }
+  hw_layer_info.sync_handle = Sys::dup_(mdp_commit.release_fence);
 
   DLOGI_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
            device_name_);
   DLOGI_IF(kTagDriverConfig, "retire_fence_fd %d", stack->retire_fence_fd);
   DLOGI_IF(kTagDriverConfig, "*******************************************************************");
 
-  Sys::close_(mdp_commit.release_fence);
+  if (mdp_commit.release_fence >= 0) {
+    Sys::close_(mdp_commit.release_fence);
+  }
 
   if (synchronous_commit_) {
     // A synchronous commit can be requested when changing the display mode so we need to update
@@ -487,6 +488,7 @@
   case kFormatRGB888:                   *target = MDP_RGB_888;           break;
   case kFormatBGR888:                   *target = MDP_BGR_888;           break;
   case kFormatRGB565:                   *target = MDP_RGB_565;           break;
+  case kFormatBGR565:                   *target = MDP_BGR_565;           break;
   case kFormatYCbCr420Planar:           *target = MDP_Y_CB_CR_H2V2;      break;
   case kFormatYCrCb420Planar:           *target = MDP_Y_CR_CB_H2V2;      break;
   case kFormatYCrCb420PlanarStride16:   *target = MDP_Y_CR_CB_GH2V2;     break;
@@ -500,7 +502,7 @@
   case kFormatYCbCr420SemiPlanarVenus:  *target = MDP_Y_CBCR_H2V2_VENUS; break;
   case kFormatRGBA8888Ubwc:             *target = MDP_RGBA_8888_UBWC;    break;
   case kFormatRGBX8888Ubwc:             *target = MDP_RGBX_8888_UBWC;    break;
-  case kFormatRGB565Ubwc:               *target = MDP_RGB_565_UBWC;      break;
+  case kFormatBGR565Ubwc:               *target = MDP_RGB_565_UBWC;      break;
   case kFormatYCbCr420SPVenusUbwc:      *target = MDP_Y_CBCR_H2V2_UBWC;  break;
   default:
     DLOGE("Unsupported format type %d", source);
@@ -534,7 +536,8 @@
     *target = width * 3;
     break;
   case kFormatRGB565:
-  case kFormatRGB565Ubwc:
+  case kFormatBGR565:
+  case kFormatBGR565Ubwc:
     *target = width * 2;
     break;
   case kFormatYCbCr420SemiPlanarVenus:
@@ -594,10 +597,6 @@
     }
   }
 
-  if (input_buffer->flags.interlace) {
-    *mdp_flags |= MDP_LAYER_DEINTERLACE;
-  }
-
   if (input_buffer->flags.secure) {
     *mdp_flags |= MDP_LAYER_SECURE_SESSION;
   }
@@ -610,7 +609,8 @@
     *mdp_flags |= MDP_LAYER_SOLID_FILL;
   }
 
-  if (layer.flags.cursor && is_cursor_pipe_used) {
+  if (hw_panel_info_.mode == kModeVideo && layer.flags.cursor && is_cursor_pipe_used) {
+    // Only video mode panels support ASYNC layer updates
     *mdp_flags |= MDP_LAYER_ASYNC;
   }
 }
@@ -1023,5 +1023,9 @@
   return kErrorNotSupported;
 }
 
+DisplayError HWDevice::GetPanelBrightness(int *level) {
+  return kErrorNotSupported;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index da43441..cde3efa 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -71,6 +71,7 @@
   virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format);
   virtual DisplayError SetCursorPosition(HWLayers *hw_layers, int x, int y);
   virtual DisplayError OnMinHdcpEncryptionLevelChange();
+  virtual DisplayError GetPanelBrightness(int *level);
 
   // For HWDevice derivatives
   virtual DisplayError Init(HWEventHandler *eventhandler);
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index 8dc0e35..61d3df8 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -279,7 +279,7 @@
   STRUCT_VAR(msmfb_metadata, metadata);
   metadata.op = metadata_op_vic;
   metadata.data.video_info_code = timing_mode->video_format;
-  if (ioctl(device_fd_, MSMFB_METADATA_SET, &metadata) < 0) {
+  if (Sys::ioctl_(device_fd_, MSMFB_METADATA_SET, &metadata) < 0) {
     IOCTL_LOGE(MSMFB_METADATA_SET, device_type_);
     return kErrorHardware;
   }
@@ -461,22 +461,16 @@
 
 // Reads the contents of res_info node into a buffer if the file is not empty
 bool HWHDMI::ReadResolutionFile(char *config_buffer) {
-  bool is_file_read = false;
-  size_t bytes_read = 0;
+  ssize_t bytes_read = 0;
   int fd = OpenResolutionFile(O_RDONLY);
-  if (fd < 0) {
-    return false;
+  if (fd >= 0) {
+    bytes_read = Sys::pread_(fd, config_buffer, kPageSize, 0);
+    Sys::close_(fd);
   }
 
-  if ((bytes_read = Sys::pread_(fd, config_buffer, kPageSize, 0)) != 0) {
-    is_file_read = true;
-  }
+  DLOGI_IF(kTagDriverConfig, "bytes_read = %d", bytes_read);
 
-  Sys::close_(fd);
-
-  DLOGI_IF(kTagDriverConfig, "bytes_read=%d is_file_read=%d", bytes_read, is_file_read);
-
-  return is_file_read;
+  return (bytes_read > 0);
 }
 
 // Populates the internal timing info structure with the timing info obtained
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index d5c913d..3c308d7 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -95,6 +95,11 @@
     goto CleanupOnError;
   }
 
+  error = PopulateDisplayAttributes();
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
   // Open nodes for polling
   for (int event = 0; event < kNumDisplayEvents; event++) {
     poll_fds_[event].fd = -1;
@@ -104,11 +109,6 @@
     for (int event = 0; event < kNumDisplayEvents; event++) {
       pollfd &poll_fd = poll_fds_[event];
 
-      if ((hw_panel_info_.mode == kModeCommand) &&
-          (!strncmp(event_name[event], "idle_notify", strlen("idle_notify")))) {
-        continue;
-      }
-
       snprintf(node_path, sizeof(node_path), "%s%d/%s", fb_path_, fb_node_index_,
                event_name[event]);
 
@@ -151,21 +151,21 @@
   return error;
 }
 
-void HWPrimary::InitializeConfigs() {
-  size_t curr_x_pixels = 0;
-  size_t curr_y_pixels = 0;
-  string mode_path = string(fb_path_) + string("0/mode");
-  string modes_path = string(fb_path_) + string("0/modes");
+bool HWPrimary::GetCurrentModeFromSysfs(size_t *curr_x_pixels, size_t *curr_y_pixels) {
+  bool ret = false;
   size_t len = kPageSize;
-  char *buffer = static_cast<char *>(calloc(len, sizeof(char)));
-
-  if (buffer == NULL) {
-    DLOGW("Failed to allocate memory");
-    return;
-  }
+  string mode_path = string(fb_path_) + string("0/mode");
 
   FILE *fd = Sys::fopen_(mode_path.c_str(), "r");
   if (fd) {
+    char *buffer = static_cast<char *>(calloc(len, sizeof(char)));
+
+    if (buffer == NULL) {
+      DLOGW("Failed to allocate memory");
+      Sys::fclose_(fd);
+      return false;
+    }
+
     if (Sys::getline_(&buffer, &len, fd) > 0) {
       // String is of form "U:1600x2560p-0". Documentation/fb/modedb.txt in
       // kernel has more info on the format.
@@ -174,21 +174,41 @@
 
       if (xpos == string::npos || ypos == string::npos) {
         DLOGI("Resolution switch not supported");
-        free(buffer);
-        Sys::fclose_(fd);
-        return;
+      } else {
+        *curr_x_pixels = atoi(buffer + xpos + 1);
+        *curr_y_pixels = atoi(buffer + ypos + 1);
+        DLOGI("Current Config: %u x %u", *curr_x_pixels, *curr_y_pixels);
+        ret = true;
       }
-
-      curr_x_pixels = atoi(buffer + xpos + 1);
-      curr_y_pixels = atoi(buffer + ypos + 1);
-      DLOGI("Current Config: %u x %u", curr_x_pixels, curr_y_pixels);
     }
 
+    free(buffer);
     Sys::fclose_(fd);
   }
 
-  fd = Sys::fopen_(modes_path.c_str(), "r");
+  return ret;
+}
+
+void HWPrimary::InitializeConfigs() {
+  size_t curr_x_pixels = 0;
+  size_t curr_y_pixels = 0;
+  size_t len = kPageSize;
+  string modes_path = string(fb_path_) + string("0/modes");
+
+  if (!GetCurrentModeFromSysfs(&curr_x_pixels, &curr_y_pixels)) {
+    return;
+  }
+
+  FILE *fd = Sys::fopen_(modes_path.c_str(), "r");
   if (fd) {
+    char *buffer = static_cast<char *>(calloc(len, sizeof(char)));
+
+    if (buffer == NULL) {
+      DLOGW("Failed to allocate memory");
+      Sys::fclose_(fd);
+      return;
+    }
+
     while (Sys::getline_(&buffer, &len, fd) > 0) {
       DisplayConfigVariableInfo config;
       size_t xpos = string(buffer).find(':');
@@ -210,27 +230,30 @@
       }
     }
 
+    free(buffer);
     Sys::fclose_(fd);
   } else {
     DLOGI("Unable to process modes");
   }
-
-  free(buffer);
 }
 
 DisplayError HWPrimary::Deinit() {
   exit_threads_ = true;
+  Sys::pthread_cancel_(event_thread_);
   pthread_join(event_thread_, NULL);
 
   for (int event = 0; event < kNumDisplayEvents; event++) {
-    Sys::close_(poll_fds_[event].fd);
+    int &fd = poll_fds_[event].fd;
+    if (fd >= 0) {
+      Sys::close_(fd);
+    }
   }
 
   return HWDevice::Deinit();
 }
 
 DisplayError HWPrimary::GetNumDisplayAttributes(uint32_t *count) {
-  *count = isResolutionSwitchEnabled() ? display_configs_.size() : 1;
+  *count = IsResolutionSwitchEnabled() ? display_configs_.size() : 1;
   return kErrorNone;
 }
 
@@ -245,24 +268,15 @@
     return kErrorParameters;
   }
 
-  if (isResolutionSwitchEnabled() && index >= display_configs_.size()) {
+  if (IsResolutionSwitchEnabled() && index >= display_configs_.size()) {
     return kErrorParameters;
   }
 
-  if (config_changed_) {
-    DisplayError error = PopulateDisplayAttributes();
-    if (error != kErrorNone) {
-      return error;
-    }
-    config_changed_ = false;
-  }
-
   *display_attributes = display_attributes_;
-  if (isResolutionSwitchEnabled()) {
+  if (IsResolutionSwitchEnabled()) {
     // Overwrite only the parent portion of object
     display_attributes->x_pixels = display_configs_.at(index).x_pixels;
     display_attributes->y_pixels = display_configs_.at(index).y_pixels;
-    display_attributes->fps = display_configs_.at(index).fps;
   }
 
   return kErrorNone;
@@ -320,7 +334,7 @@
 DisplayError HWPrimary::SetDisplayAttributes(uint32_t index) {
   DisplayError ret = kErrorNone;
 
-  if (!isResolutionSwitchEnabled()) {
+  if (!IsResolutionSwitchEnabled()) {
     return kErrorNotSupported;
   }
 
@@ -355,7 +369,9 @@
 DisplayError HWPrimary::SetRefreshRate(uint32_t refresh_rate) {
   char node_path[kMaxStringLength] = {0};
 
-  DLOGI("Setting refresh rate to = %d fps", refresh_rate);
+  if (refresh_rate == display_attributes_.fps) {
+    return kErrorNone;
+  }
 
   snprintf(node_path, sizeof(node_path), "%s%d/dynamic_fps", fb_path_, fb_node_index_);
 
@@ -375,8 +391,10 @@
   }
   Sys::close_(fd);
 
-  config_changed_ = true;
-  synchronous_commit_ = true;
+  DisplayError error = PopulateDisplayAttributes();
+  if (error != kErrorNone) {
+    return error;
+  }
 
   return kErrorNone;
 }
@@ -545,7 +563,7 @@
 
   // Notify driver about the timeout value
   ssize_t length = Sys::pwrite_(fd, timeout_string, strlen(timeout_string), 0);
-  if (length < -1) {
+  if (length <= 0) {
     DLOGE("Unable to write into %s, node %s", node_path, strerror(errno));
   }
 
@@ -592,31 +610,56 @@
 }
 
 DisplayError HWPrimary::SetPanelBrightness(int level) {
-  char buffer[MAX_SYSFS_COMMAND_LENGTH];
-  int32_t bytes, bl_fd = -1;
-  ssize_t ret;
-
-  memset(buffer, 0, MAX_SYSFS_COMMAND_LENGTH);
+  char buffer[MAX_SYSFS_COMMAND_LENGTH] = {0};
 
   DLOGV_IF(kTagDriverConfig, "Set brightness level to %d", level);
-  bl_fd = Sys::open_("/sys/class/leds/lcd-backlight/brightness", O_RDWR);
-  if (bl_fd < 0) {
-    DLOGI("SetPanelBrightness: open failed out :( %d", level);
-    return kErrorParameters;
+  int fd = Sys::open_(kBrightnessNode, O_RDWR);
+  if (fd < 0) {
+    DLOGV_IF(kTagDriverConfig, "Failed to open node = %s, error = %s ", kBrightnessNode,
+             strerror(errno));
+    return kErrorFileDescriptor;
   }
-  bytes = snprintf(buffer, MAX_SYSFS_COMMAND_LENGTH, "%d\n", level);
+
+  int32_t bytes = snprintf(buffer, MAX_SYSFS_COMMAND_LENGTH, "%d\n", level);
   if (bytes < 0) {
-    DLOGE("SetPanelBrightness: snprintf failed out :( %d", level);
-    Sys::close_(bl_fd);
-    return kErrorParameters;
+    DLOGV_IF(kTagDriverConfig, "Failed to copy new brightness level = %d", level);
+    Sys::close_(fd);
+    return kErrorUndefined;
   }
-  ret = Sys::pwrite_(bl_fd, buffer, bytes, 0);
+
+  ssize_t ret = Sys::pwrite_(fd, buffer, bytes, 0);
   if (ret <= 0) {
-    DLOGE("SetPanelBrightness: write failed out :( %d", level);
-    Sys::close_(bl_fd);
+    DLOGV_IF(kTagDriverConfig, "Failed to write to node = %s, error = %s ", kBrightnessNode,
+             strerror(errno));
+    Sys::close_(fd);
+    return kErrorUndefined;
+  }
+  Sys::close_(fd);
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::GetPanelBrightness(int *level) {
+  char brightness[kMaxStringLength] = {0};
+
+  if (!level) {
+    DLOGV_IF(kTagDriverConfig, "Invalid input, null pointer.");
     return kErrorParameters;
   }
-  Sys::close_(bl_fd);
+
+  int fd = Sys::open_(kBrightnessNode, O_RDWR);
+  if (fd < 0) {
+    DLOGV_IF(kTagDriverConfig, "Failed to open brightness node = %s, error = %s", kBrightnessNode,
+             strerror(errno));
+    return kErrorFileDescriptor;
+  }
+
+  if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
+    *level = atoi(brightness);
+    DLOGV_IF(kTagDriverConfig, "Brightness level = %d", *level);
+  }
+  Sys::close_(fd);
+
   return kErrorNone;
 }
 
diff --git a/sdm/libs/core/fb/hw_primary.h b/sdm/libs/core/fb/hw_primary.h
index 2f052fc..b0507c6 100644
--- a/sdm/libs/core/fb/hw_primary.h
+++ b/sdm/libs/core/fb/hw_primary.h
@@ -62,6 +62,7 @@
   virtual DisplayError SetPanelBrightness(int level);
   virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
   virtual DisplayError SetPPFeatures(PPFeaturesConfig *feature_list);
+  virtual DisplayError GetPanelBrightness(int *level);
 
  private:
   // Panel modes for the MSMFB_LPM_ENABLE ioctl
@@ -80,7 +81,8 @@
   void HandleThermal(char *data);
   DisplayError PopulateDisplayAttributes();
   void InitializeConfigs();
-  bool isResolutionSwitchEnabled() { return !display_configs_.empty(); }
+  bool IsResolutionSwitchEnabled() { return !display_configs_.empty(); }
+  bool GetCurrentModeFromSysfs(size_t *curr_x_pixels, size_t *curr_y_pixels);
 
   pollfd poll_fds_[kNumDisplayEvents];
   pthread_t event_thread_;
@@ -88,10 +90,10 @@
   bool fake_vsync_ = false;
   bool exit_threads_ = false;
   HWDisplayAttributes display_attributes_;
-  bool config_changed_ = true;
   std::vector<DisplayConfigVariableInfo> display_configs_;
   std::vector<std::string> display_config_strings_;
   uint32_t active_config_index_ = 0;
+  const char *kBrightnessNode = "/sys/class/leds/lcd-backlight/brightness";
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index c6e3e50..648c313 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -89,6 +89,7 @@
   virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format) = 0;
   virtual DisplayError SetCursorPosition(HWLayers *hw_layers, int x, int y) = 0;
   virtual DisplayError OnMinHdcpEncryptionLevelChange() = 0;
+  virtual DisplayError GetPanelBrightness(int *level) = 0;
 
  protected:
   virtual ~HWInterface() { }
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index 5034bac..e421961 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -918,7 +918,7 @@
   switch (format) {
   case kFormatRGBA8888Ubwc:
   case kFormatRGBX8888Ubwc:
-  case kFormatRGB565Ubwc:
+  case kFormatBGR565Ubwc:
   case kFormatYCbCr420SPVenusUbwc:
     return true;
   default:
diff --git a/sdm/libs/hwc/blit_engine_c2d.cpp b/sdm/libs/hwc/blit_engine_c2d.cpp
index 1c81016..e85e28c 100644
--- a/sdm/libs/hwc/blit_engine_c2d.cpp
+++ b/sdm/libs/hwc/blit_engine_c2d.cpp
@@ -285,6 +285,7 @@
     layer.plane_alpha = 0xFF;
     layer.blending = kBlendingOpaque;
     layer.composition = kCompositionBlitTarget;
+    layer.frame_rate = layer_stack->layers[gpu_target_index].frame_rate;
   }
 
   return 0;
@@ -522,7 +523,7 @@
   switch (format) {
   case kFormatRGBA8888Ubwc:
   case kFormatRGBX8888Ubwc:
-  case kFormatRGB565Ubwc:
+  case kFormatBGR565Ubwc:
   case kFormatYCbCr420SPVenusUbwc:
     return true;
   default:
diff --git a/sdm/libs/hwc/hwc_buffer_allocator.cpp b/sdm/libs/hwc/hwc_buffer_allocator.cpp
index 54dbefb..1ea2915 100644
--- a/sdm/libs/hwc/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc/hwc_buffer_allocator.cpp
@@ -78,6 +78,7 @@
 
   error = SetBufferInfo(buffer_config.format, &format, &alloc_flags);
   if (error != 0) {
+    delete meta_buffer_info;
     return kErrorParameters;
   }
 
@@ -96,6 +97,7 @@
   error = alloc_controller_->allocate(data, alloc_flags);
   if (error != 0) {
     DLOGE("Error allocating memory size %d uncached %d", data.size, data.uncached);
+    delete meta_buffer_info;
     return kErrorMemory;
   }
 
@@ -153,6 +155,7 @@
   case kFormatRGBX8888:                 *target = HAL_PIXEL_FORMAT_RGBX_8888;             break;
   case kFormatRGB888:                   *target = HAL_PIXEL_FORMAT_RGB_888;               break;
   case kFormatRGB565:                   *target = HAL_PIXEL_FORMAT_RGB_565;               break;
+  case kFormatBGR565:                   *target = HAL_PIXEL_FORMAT_BGR_565;               break;
   case kFormatBGRA8888:                 *target = HAL_PIXEL_FORMAT_BGRA_8888;             break;
   case kFormatYCrCb420PlanarStride16:   *target = HAL_PIXEL_FORMAT_YV12;                  break;
   case kFormatYCrCb420SemiPlanar:       *target = HAL_PIXEL_FORMAT_YCrCb_420_SP;          break;
@@ -171,8 +174,8 @@
     *target = HAL_PIXEL_FORMAT_RGBX_8888;
     *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
     break;
-  case kFormatRGB565Ubwc:
-    *target = HAL_PIXEL_FORMAT_RGB_565;
+  case kFormatBGR565Ubwc:
+    *target = HAL_PIXEL_FORMAT_BGR_565;
     *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
     break;
   default:
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index 602c416..3245eb6 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -43,22 +43,25 @@
 
 namespace sdm {
 
-void HWCDisplay::AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height,
-                                        uint32_t *src_width, uint32_t *src_height) {
-  *src_height = (dst_width * (*src_height)) / (*src_width);
-  *src_width = dst_width;
+static void AssignLayerRegionsAddress(LayerRectArray *region, uint32_t rect_count,
+                                      uint8_t **base_address) {
+  if (rect_count) {
+    region->rect = reinterpret_cast<LayerRect *>(*base_address);
+    region->count = rect_count;
+    for (size_t i = 0; i < rect_count; i++) {
+      region->rect[i] = LayerRect();
+    }
+    *base_address += rect_count * sizeof(LayerRect);
+  }
 }
 
-void HWCDisplay::GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
-                                        uint32_t *non_primary_width, uint32_t *non_primary_height) {
-  uint32_t primary_area = primary_width * primary_height;
-  uint32_t non_primary_area = (*non_primary_width) * (*non_primary_height);
-
-  if (primary_area > non_primary_area) {
-    if (primary_height > primary_width) {
-      Swap(primary_height, primary_width);
-    }
-    AdjustSourceResolution(primary_width, primary_height, non_primary_width, non_primary_height);
+static void ApplyDeInterlaceAdjustment(Layer *layer) {
+  // De-interlacing adjustment
+  if (layer->input_buffer->flags.interlace) {
+    float height = (layer->src_rect.bottom - layer->src_rect.top) / 2.0f;
+    layer->src_rect.bottom = layer->src_rect.top + floorf(height);
+    layer->input_buffer->height /= 2;
+    layer->input_buffer->width *= 2;
   }
 }
 
@@ -101,6 +104,9 @@
     }
   }
 
+  display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
+  current_refresh_rate_ = max_refresh_rate_;
+
   return 0;
 }
 
@@ -275,19 +281,7 @@
 }
 
 DisplayError HWCDisplay::Refresh() {
-  const hwc_procs_t *hwc_procs = *hwc_procs_;
-
-  if (!hwc_procs) {
-    return kErrorParameters;
-  }
-
-  if (!handle_refresh_) {
-    return kErrorNotSupported;
-  }
-
-  hwc_procs->invalidate(hwc_procs);
-
-  return kErrorNone;
+  return kErrorNotSupported;
 }
 
 int HWCDisplay::AllocateLayerStack(hwc_display_contents_1_t *content_list) {
@@ -303,19 +297,27 @@
     blit_target_count = kMaxBlitTargetLayers;
   }
 
-  // Allocate memory for a) total number of layers b) buffer handle for each layer c) number of
-  // visible rectangles in each layer d) dirty rectangle for each layer
+  // Allocate memory for
+  //  a) total number of layers
+  //  b) buffer handle for each layer
+  //  c) number of visible rectangles in each layer
+  //  d) number of dirty rectangles in each layer
+  //  e) number of blit rectangles in each layer
   size_t required_size = (num_hw_layers + blit_target_count) *
                          (sizeof(Layer) + sizeof(LayerBuffer));
 
   for (size_t i = 0; i < num_hw_layers + blit_target_count; i++) {
-    uint32_t num_visible_rects = 1;
+    uint32_t num_visible_rects = 0;
+    uint32_t num_dirty_rects = 0;
+
+    hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
     if (i < num_hw_layers) {
-      num_visible_rects = INT32(content_list->hwLayers[i].visibleRegionScreen.numRects);
+      num_visible_rects = INT32(hwc_layer.visibleRegionScreen.numRects);
+      num_dirty_rects = INT32(hwc_layer.surfaceDamage.numRects);
     }
 
-    // visible rectangles + 1 dirty rectangle + blit rectangle
-    size_t num_rects = num_visible_rects + 1 + blit_target_count;
+    // visible rectangles + dirty rectangles + blit rectangle
+    size_t num_rects = num_visible_rects + num_dirty_rects + blit_target_count;
     required_size += num_rects * sizeof(LayerRect);
   }
 
@@ -347,10 +349,12 @@
   current_address += (num_hw_layers + blit_target_count) * sizeof(Layer);
 
   for (size_t i = 0; i < num_hw_layers + blit_target_count; i++) {
-    uint32_t num_visible_rects = 1;
+    uint32_t num_visible_rects = 0;
+    uint32_t num_dirty_rects = 0;
+
     if (i < num_hw_layers) {
-      num_visible_rects =
-        static_cast<uint32_t>(content_list->hwLayers[i].visibleRegionScreen.numRects);
+      num_visible_rects = UINT32(content_list->hwLayers[i].visibleRegionScreen.numRects);
+      num_dirty_rects = UINT32(content_list->hwLayers[i].surfaceDamage.numRects);
     }
 
     Layer &layer = layer_stack_.layers[i];
@@ -361,39 +365,21 @@
     *layer.input_buffer = LayerBuffer();
     current_address += sizeof(LayerBuffer);
 
-    // Visible rectangle address
-    layer.visible_regions.rect = reinterpret_cast<LayerRect *>(current_address);
-    layer.visible_regions.count = num_visible_rects;
-    for (size_t i = 0; i < layer.visible_regions.count; i++) {
-      layer.visible_regions.rect[i] = LayerRect();
-    }
-    current_address += num_visible_rects * sizeof(LayerRect);
-
-    // Dirty rectangle address
-    layer.dirty_regions.rect = reinterpret_cast<LayerRect *>(current_address);
-    layer.dirty_regions.count = 1;
-    *layer.dirty_regions.rect = LayerRect();
-    current_address += sizeof(LayerRect);
-
-    // Blit rectangle address
-    layer.blit_regions.rect = reinterpret_cast<LayerRect *>(current_address);
-    layer.blit_regions.count = blit_target_count;
-    for (size_t i = 0; i < layer.blit_regions.count; i++) {
-      layer.blit_regions.rect[i] = LayerRect();
-    }
-    current_address += layer.blit_regions.count * sizeof(LayerRect);
+    // Visible/Dirty/Blit rectangle address
+    AssignLayerRegionsAddress(&layer.visible_regions, num_visible_rects, &current_address);
+    AssignLayerRegionsAddress(&layer.dirty_regions, num_dirty_rects, &current_address);
+    AssignLayerRegionsAddress(&layer.blit_regions, blit_target_count, &current_address);
   }
 
   return 0;
 }
 
-int HWCDisplay::PrepareLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer, uint32_t fps) {
+int HWCDisplay::PrepareLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer) {
   const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer->handle);
 
   LayerBuffer *layer_buffer = layer->input_buffer;
 
   if (pvt_handle) {
-    layer->frame_rate = fps;
     layer_buffer->format = GetSDMFormat(pvt_handle->format, pvt_handle->flags);
 
     const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata);
@@ -453,7 +439,6 @@
       layer_buffer->width = aligned_width;
       layer_buffer->height = aligned_height;
       layer_buffer->format = GetSDMFormat(format, flags);
-      layer->frame_rate = fps;
     }
   }
 
@@ -489,18 +474,9 @@
   }
 
   size_t num_hw_layers = content_list->numHwLayers;
-  if (num_hw_layers <= 1) {
-    flush_ = true;
-    return 0;
-  }
 
-  DisplayConfigVariableInfo active_config;
-  uint32_t active_config_index = 0;
-  display_intf_->GetActiveConfig(&active_config_index);
-  int ret;
-
-  display_intf_->GetConfig(active_config_index, &active_config);
   use_blit_comp_ = false;
+  metadata_refresh_rate_ = 0;
 
   // Configure each layer
   for (size_t i = 0; i < num_hw_layers; i++) {
@@ -508,8 +484,7 @@
 
     Layer &layer = layer_stack_.layers[i];
 
-    ret = PrepareLayerParams(&content_list->hwLayers[i], &layer_stack_.layers[i],
-                             active_config.fps);
+    int ret = PrepareLayerParams(&content_list->hwLayers[i], &layer_stack_.layers[i]);
 
     if (ret != kErrorNone) {
       return ret;
@@ -521,10 +496,14 @@
 
     SetRect(scaled_display_frame, &layer.dst_rect);
     SetRect(hwc_layer.sourceCropf, &layer.src_rect);
+    ApplyDeInterlaceAdjustment(&layer);
+
     for (size_t j = 0; j < hwc_layer.visibleRegionScreen.numRects; j++) {
       SetRect(hwc_layer.visibleRegionScreen.rects[j], &layer.visible_regions.rect[j]);
     }
-    SetRect(hwc_layer.sourceCropf, &layer.dirty_regions.rect[0]);
+    for (size_t j = 0; j < hwc_layer.surfaceDamage.numRects; j++) {
+      SetRect(hwc_layer.surfaceDamage.rects[j], &layer.dirty_regions.rect[j]);
+    }
     SetComposition(hwc_layer.compositionType, &layer.composition);
 
     // For dim layers, SurfaceFlinger
@@ -560,7 +539,7 @@
       layer.src_rect.top = 0;
       layer.src_rect.right = input_buffer->width;
       layer.src_rect.bottom = input_buffer->height;
-      layer.dirty_regions.rect[0] = layer.src_rect;
+      layer.dirty_regions.count = 0;
     }
 
     layer.plane_alpha = hwc_layer.planeAlpha;
@@ -583,6 +562,12 @@
     if (layer.flags.cursor) {
       layer_stack_.flags.cursor_present = true;
     }
+
+    if (layer.frame_rate > metadata_refresh_rate_) {
+      metadata_refresh_rate_ = SanitizeRefreshRate(layer.frame_rate);
+    } else {
+      layer.frame_rate = current_refresh_rate_;
+    }
   }
 
   // Prepare the Blit Target
@@ -623,8 +608,6 @@
     flush_ = true;
   }
 
-  metadata_refresh_rate_ = 0;
-
   // If current draw cycle has different set of layers updating in comparison to previous cycle,
   // cache content using GPU again.
   // If set of updating layers remains same, use cached buffer and replace layers marked for GPU
@@ -640,10 +623,6 @@
     if ((composition == kCompositionSDE) || (composition == kCompositionHybrid) ||
         (composition == kCompositionBlit)) {
       hwc_layer.hints |= HWC_HINT_CLEAR_FB;
-
-      if (use_metadata_refresh_rate_ && layer.frame_rate > metadata_refresh_rate_) {
-        metadata_refresh_rate_ = layer.frame_rate;
-      }
     }
 
     if (!needs_fb_refresh && composition == kCompositionGPU) {
@@ -917,7 +896,7 @@
     switch (source) {
     case HAL_PIXEL_FORMAT_RGBA_8888:          format = kFormatRGBA8888Ubwc;            break;
     case HAL_PIXEL_FORMAT_RGBX_8888:          format = kFormatRGBX8888Ubwc;            break;
-    case HAL_PIXEL_FORMAT_RGB_565:            format = kFormatRGB565Ubwc;              break;
+    case HAL_PIXEL_FORMAT_BGR_565:            format = kFormatBGR565Ubwc;              break;
     case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
     case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
     case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:    format = kFormatYCbCr420SPVenusUbwc;     break;
@@ -937,6 +916,7 @@
   case HAL_PIXEL_FORMAT_BGRX_8888:                format = kFormatBGRX8888;                 break;
   case HAL_PIXEL_FORMAT_RGB_888:                  format = kFormatRGB888;                   break;
   case HAL_PIXEL_FORMAT_RGB_565:                  format = kFormatRGB565;                   break;
+  case HAL_PIXEL_FORMAT_BGR_565:                  format = kFormatBGR565;                   break;
   case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
   case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:       format = kFormatYCbCr420SemiPlanarVenus;  break;
   case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:  format = kFormatYCbCr420SPVenusUbwc;      break;
@@ -1014,6 +994,8 @@
     return "RGB_888";
   case HAL_PIXEL_FORMAT_RGB_565:
     return "RGB_565";
+  case HAL_PIXEL_FORMAT_BGR_565:
+    return "BGR_565";
   case HAL_PIXEL_FORMAT_BGRA_8888:
     return "BGRA_8888";
   case HAL_PIXEL_FORMAT_RGBA_5551:
@@ -1304,6 +1286,15 @@
   return ret;
 }
 
+int HWCDisplay::GetPanelBrightness(int *level) {
+  return display_intf_->GetPanelBrightness(level);
+}
+
+int HWCDisplay::ToggleScreenUpdates(bool enable) {
+  display_paused_ = enable ? false : true;
+  return 0;
+}
+
 int HWCDisplay::ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
                                      PPDisplayAPIPayload *out_payload,
                                      PPPendingParams *pending_action) {
@@ -1348,5 +1339,33 @@
   return display_intf_->GetConfig(config, attributes) == kErrorNone ? 0 : -1;
 }
 
-}  // namespace sdm
+bool HWCDisplay::SingleLayerUpdating(uint32_t app_layer_count) {
+  uint32_t updating_count = 0;
 
+  for (uint i = 0; i < app_layer_count; i++) {
+    Layer &layer = layer_stack_.layers[i];
+    if (layer.flags.updating) {
+      updating_count++;
+    }
+  }
+
+  return (updating_count == 1);
+}
+
+uint32_t HWCDisplay::SanitizeRefreshRate(uint32_t req_refresh_rate) {
+  uint32_t refresh_rate = req_refresh_rate;
+
+  if (refresh_rate < min_refresh_rate_) {
+    // Pick the next multiple of request which is within the range
+    refresh_rate = (((min_refresh_rate_ / refresh_rate) +
+                     ((min_refresh_rate_ % refresh_rate) ? 1 : 0)) * refresh_rate);
+  }
+
+  if (refresh_rate > max_refresh_rate_) {
+    refresh_rate = max_refresh_rate_;
+  }
+
+  return refresh_rate;
+}
+
+}  // namespace sdm
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index edb7a81..3714a95 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -36,6 +36,7 @@
 
 class HWCDisplay : public DisplayEventHandler {
  public:
+  virtual ~HWCDisplay() { }
   virtual int Init();
   virtual int Deinit();
   virtual int Prepare(hwc_display_contents_1_t *content_list) = 0;
@@ -61,7 +62,6 @@
   virtual int OnMinHdcpEncryptionLevelChange();
   virtual int Perform(uint32_t operation, ...);
   virtual int SetCursorPosition(int x, int y);
-  virtual ~HWCDisplay() { }
   virtual void SetSecureDisplay(bool secure_display_active);
 
   // Display Configurations
@@ -71,6 +71,8 @@
   virtual int GetDisplayAttributesForConfig(int config, DisplayConfigVariableInfo *attributes);
 
   int SetPanelBrightness(int level);
+  int GetPanelBrightness(int *level);
+  int ToggleScreenUpdates(bool enable);
   int ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload,
                            PPDisplayAPIPayload *out_payload,
                            PPPendingParams *pending_action);
@@ -84,7 +86,7 @@
   };
 
   // Dim layer flag set by SurfaceFlinger service.
-  static const uint32_t kDimLayer = 0x8000;
+  static const uint32_t kDimLayer = 0x80000000;
 
   // Maximum number of layers supported by display manager.
   static const uint32_t kMaxLayerCount = 32;
@@ -145,11 +147,8 @@
   bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list);
   void CacheLayerStackInfo(hwc_display_contents_1_t *content_list);
   bool IsLayerUpdating(const hwc_layer_1_t &hwc_layer, const LayerCache &layer_cache);
-
-  static void AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height, uint32_t *src_width,
-                                     uint32_t *src_height);
-  static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
-                                     uint32_t *virtual_width, uint32_t *virtual_height);
+  bool SingleLayerUpdating(uint32_t app_layer_count);
+  uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
 
   enum {
     INPUT_LAYER_DUMP,
@@ -173,8 +172,12 @@
   bool swap_interval_zero_ = false;
   DisplayConfigVariableInfo *framebuffer_config_ = NULL;
   bool display_paused_ = false;
+  uint32_t min_refresh_rate_ = 0;
+  uint32_t max_refresh_rate_ = 0;
+  uint32_t current_refresh_rate_ = 0;
   bool use_metadata_refresh_rate_ = false;
   uint32_t metadata_refresh_rate_ = 0;
+  uint32_t force_refresh_rate_ = 0;
   bool boot_animation_completed_ = false;
   bool shutdown_pending_ = false;
   bool handle_refresh_ = true;
@@ -183,12 +186,12 @@
   bool skip_prepare_ = false;
 
   bool solid_fill_enable_ = false;
-  uint32_t solid_fill_color_;
+  uint32_t solid_fill_color_ = 0;;
 
  private:
   bool IsFrameBufferScaled();
   void DumpInputBuffers(hwc_display_contents_1_t *content_list);
-  int PrepareLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer, uint32_t fps);
+  int PrepareLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer);
   void CommitLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer);
   void ResetLayerCacheStack();
   BlitEngine *blit_engine_ = NULL;
diff --git a/sdm/libs/hwc/hwc_display_external.cpp b/sdm/libs/hwc/hwc_display_external.cpp
index 606227b..9053b42 100644
--- a/sdm/libs/hwc/hwc_display_external.cpp
+++ b/sdm/libs/hwc/hwc_display_external.cpp
@@ -91,6 +91,12 @@
     return status;
   }
 
+  size_t num_hw_layers = content_list->numHwLayers;
+  if (num_hw_layers <= 1) {
+    flush_ = true;
+    return 0;
+  }
+
   status = PrepareLayerStack(content_list);
   if (status) {
     return status;
@@ -168,5 +174,24 @@
   return;
 }
 
+static void AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height, uint32_t *src_width,
+                                   uint32_t *src_height) {
+  *src_height = (dst_width * (*src_height)) / (*src_width);
+  *src_width = dst_width;
+}
+
+void HWCDisplayExternal::GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
+                                        uint32_t *non_primary_width, uint32_t *non_primary_height) {
+  uint32_t primary_area = primary_width * primary_height;
+  uint32_t non_primary_area = (*non_primary_width) * (*non_primary_height);
+
+  if (primary_area > non_primary_area) {
+    if (primary_height > primary_width) {
+      Swap(primary_height, primary_width);
+    }
+    AdjustSourceResolution(primary_width, primary_height, non_primary_width, non_primary_height);
+  }
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/hwc/hwc_display_external.h b/sdm/libs/hwc/hwc_display_external.h
index f6c5f42..ba00d4d 100644
--- a/sdm/libs/hwc/hwc_display_external.h
+++ b/sdm/libs/hwc/hwc_display_external.h
@@ -41,6 +41,8 @@
  private:
   HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
   void ApplyScanAdjustment(hwc_rect_t *display_frame);
+  static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
+                                     uint32_t *virtual_width, uint32_t *virtual_height);
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/hwc/hwc_display_primary.cpp b/sdm/libs/hwc/hwc_display_primary.cpp
index d1a0e0a..d12bd1d 100644
--- a/sdm/libs/hwc/hwc_display_primary.cpp
+++ b/sdm/libs/hwc/hwc_display_primary.cpp
@@ -86,6 +86,13 @@
     cpu_hint_ = NULL;
   }
 
+  use_metadata_refresh_rate_ = true;
+  int disable_metadata_dynfps = 0;
+  HWCDebugHandler::Get()->GetProperty("persist.metadata_dynfps.disable", &disable_metadata_dynfps);
+  if (disable_metadata_dynfps) {
+    use_metadata_refresh_rate_ = false;
+  }
+
   return HWCDisplay::Init();
 }
 
@@ -109,11 +116,22 @@
   if (!boot_animation_completed_)
     ProcessBootAnimCompleted();
 
+  if (display_paused_) {
+    MarkLayersForGPUBypass(content_list);
+    return status;
+  }
+
   status = AllocateLayerStack(content_list);
   if (status) {
     return status;
   }
 
+  size_t num_hw_layers = content_list->numHwLayers;
+  if (num_hw_layers <= 1) {
+    flush_ = true;
+    return 0;
+  }
+
   status = PrepareLayerStack(content_list);
   if (status) {
     return status;
@@ -141,17 +159,27 @@
     }
   }
 
-  if (use_metadata_refresh_rate_) {
-    SetRefreshRate(metadata_refresh_rate_);
-  }
-
-  ToggleCPUHint(app_layer_count);
-
   return 0;
 }
 
 int HWCDisplayPrimary::Commit(hwc_display_contents_1_t *content_list) {
   int status = 0;
+  if (display_paused_) {
+    if (content_list->outbufAcquireFenceFd >= 0) {
+      // If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd,
+      // which will make sure the framework waits on it and closes it.
+      content_list->retireFenceFd = dup(content_list->outbufAcquireFenceFd);
+      close(content_list->outbufAcquireFenceFd);
+      content_list->outbufAcquireFenceFd = -1;
+    }
+    CloseAcquireFences(content_list);
+
+    DisplayError error = display_intf_->Flush();
+    if (error != kErrorNone) {
+      DLOGE("Flush failed. Error = %d", error);
+    }
+    return status;
+  }
 
   status = HWCDisplay::CommitLayerStack(content_list);
   if (status) {
@@ -163,6 +191,11 @@
     return status;
   }
 
+  bool one_updating_layer = SingleLayerUpdating(content_list->numHwLayers - 1);
+
+  SetMetadataRefreshRate(one_updating_layer);
+  ToggleCPUHint(one_updating_layer);
+
   return 0;
 }
 
@@ -173,7 +206,7 @@
     error = display_intf_->SetRefreshRate(refresh_rate);
   }
 
-  return error;
+  return (error ? -1 : 0);
 }
 
 int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
@@ -186,7 +219,7 @@
       SetMetaDataRefreshRateFlag(val);
       break;
     case SET_BINDER_DYN_REFRESH_RATE:
-      SetRefreshRate(val);
+      ForceRefreshRate(val);
       break;
     case SET_DISPLAY_MODE:
       SetDisplayMode(val);
@@ -216,6 +249,12 @@
 }
 
 void HWCDisplayPrimary::SetMetaDataRefreshRateFlag(bool enable) {
+  int disable_metadata_dynfps = 0;
+
+  HWCDebugHandler::Get()->GetProperty("persist.metadata_dynfps.disable", &disable_metadata_dynfps);
+  if (disable_metadata_dynfps) {
+    return;
+  }
   use_metadata_refresh_rate_ = enable;
 }
 
@@ -224,21 +263,12 @@
   solid_fill_color_  = color;
 }
 
-void HWCDisplayPrimary::ToggleCPUHint(int app_layer_count) {
-  int updating_count = 0;
-
+void HWCDisplayPrimary::ToggleCPUHint(bool set) {
   if (!cpu_hint_) {
     return;
   }
 
-  for (int i = 0; i < app_layer_count; i++) {
-    Layer &layer = layer_stack_.layers[i];
-    if (layer.flags.updating) {
-      updating_count++;
-    }
-  }
-
-  if (updating_count == 1) {
+  if (set) {
     cpu_hint_->Set();
   } else {
     cpu_hint_->Reset();
@@ -256,5 +286,79 @@
   return;
 }
 
+void HWCDisplayPrimary::SetMetadataRefreshRate(bool one_updating_layer) {
+  // return if force_refresh_rate_ is set or metadata_refresh_rate is not enabled
+  if (force_refresh_rate_) {
+    return;
+  }
+
+  uint32_t refresh_rate = max_refresh_rate_;
+  if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
+    refresh_rate = metadata_refresh_rate_;
+  }
+
+  int status = SetRefreshRate(refresh_rate);
+  if (status == 0) {
+    // Set current refresh rate to metadata refresh rate
+    current_refresh_rate_ = refresh_rate;
+  } else {
+    // Failed - Restore to max refresh rate
+    current_refresh_rate_ = max_refresh_rate_;
+  }
+}
+
+void HWCDisplayPrimary::ForceRefreshRate(uint32_t refresh_rate) {
+  if (refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) {
+    // Cannot honor force refresh rate, as its beyond the range
+    return;
+  }
+
+  uint32_t rate = refresh_rate;
+  force_refresh_rate_ = refresh_rate;
+  if (refresh_rate == 0) {
+    // refresh rate request of 0 means the client is resetting the forced request rate
+    rate = max_refresh_rate_;
+  }
+
+  int status = SetRefreshRate(rate);
+  if (status) {
+    // failed Reset force_refresh_rate to 0, and restore max refresh rate
+    force_refresh_rate_ = 0;
+    rate = max_refresh_rate_;
+    DLOGE("Setting Refresh Rate = %d Failed", refresh_rate);
+  }
+  current_refresh_rate_ = rate;
+
+  return;
+}
+
+DisplayError HWCDisplayPrimary::Refresh() {
+  const hwc_procs_t *hwc_procs = *hwc_procs_;
+  DisplayError error = kErrorNone;
+
+  if (!hwc_procs) {
+    return kErrorParameters;
+  }
+
+  if (!handle_refresh_) {
+    error = kErrorNotSupported;
+  }
+
+  if (error == kErrorNone) {
+    hwc_procs->invalidate(hwc_procs);
+  }
+
+  uint32_t refresh_rate = force_refresh_rate_ ? force_refresh_rate_ : min_refresh_rate_;
+
+  int status = SetRefreshRate(refresh_rate);
+  if (status) {
+    DLOGE("Setting Refresh Rate = %d Failed", refresh_rate);
+  } else {
+    current_refresh_rate_ = refresh_rate;
+  }
+
+  return error;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/hwc/hwc_display_primary.h b/sdm/libs/hwc/hwc_display_primary.h
index a10e8c3..230d2d5 100644
--- a/sdm/libs/hwc/hwc_display_primary.h
+++ b/sdm/libs/hwc/hwc_display_primary.h
@@ -49,6 +49,7 @@
   virtual int SetRefreshRate(uint32_t refresh_rate);
   virtual int Perform(uint32_t operation, ...);
   virtual void SetSecureDisplay(bool secure_display_active);
+  virtual DisplayError Refresh();
 
  private:
   HWCDisplayPrimary(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
@@ -56,7 +57,9 @@
   virtual DisplayError SetDisplayMode(uint32_t mode);
   void ProcessBootAnimCompleted();
   void SetQDCMSolidFillInfo(bool enable, uint32_t color);
-  void ToggleCPUHint(int app_layer_count);
+  void ToggleCPUHint(bool set);
+  void SetMetadataRefreshRate(bool one_updating_layer);
+  void ForceRefreshRate(uint32_t refresh_rate);
 
   CPUHint *cpu_hint_;
 };
diff --git a/sdm/libs/hwc/hwc_display_virtual.cpp b/sdm/libs/hwc/hwc_display_virtual.cpp
index 10a8ec2..116c36d 100644
--- a/sdm/libs/hwc/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc/hwc_display_virtual.cpp
@@ -39,24 +39,6 @@
 
 namespace sdm {
 
-static int GetWidthFromMetaData(const private_handle_t *handle) {
-  MetaData_t *metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
-  if (metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
-    return metadata->bufferDim.sliceWidth;
-  }
-
-  return handle->width;
-}
-
-static int GetHeightFromMetaData(const private_handle_t *handle) {
-  MetaData_t *metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
-  if (metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
-    return metadata->bufferDim.sliceHeight;
-  }
-
-  return handle->height;
-}
-
 int HWCDisplayVirtual::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
                               uint32_t primary_width, uint32_t primary_height,
                               hwc_display_contents_1_t *content_list,
@@ -77,20 +59,26 @@
     return status;
   }
 
+  // TODO(user): Need to update resolution(and not aligned resolution) on writeback.
   status = hwc_display_virtual->SetOutputSliceFromMetadata(content_list);
   if (status) {
+    Destroy(hwc_display_virtual);
     return status;
   }
 
   hwc_display_virtual->GetPanelResolution(&virtual_width, &virtual_height);
 
-  int downscale_enabled = 0;
-  HWCDebugHandler::Get()->GetProperty("sdm.debug.sde_downscale_virtual", &downscale_enabled);
-  if (downscale_enabled) {
-    GetDownscaleResolution(primary_width, primary_height, &virtual_width, &virtual_height);
+  if (content_list->numHwLayers < 1) {
+    Destroy(hwc_display_virtual);
+    return -1;
   }
 
-  status = hwc_display_virtual->SetFrameBufferResolution(virtual_width, virtual_height);
+  hwc_layer_1_t &fb_layer = content_list->hwLayers[content_list->numHwLayers-1];
+  int fb_width = fb_layer.displayFrame.right - fb_layer.displayFrame.left;
+  int fb_height = fb_layer.displayFrame.bottom - fb_layer.displayFrame.top;
+
+  status = hwc_display_virtual->SetFrameBufferResolution(fb_width, fb_height);
+
   if (status) {
     Destroy(hwc_display_virtual);
     return status;
@@ -212,13 +200,21 @@
   int status = 0;
 
   if (output_handle) {
-    LayerBufferFormat format = GetSDMFormat(output_handle->format, output_handle->flags);
+    int output_handle_format = output_handle->format;
+    if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
+      output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
+    }
+
+    LayerBufferFormat format = GetSDMFormat(output_handle_format, output_handle->flags);
     if (format == kFormatInvalid) {
       return -EINVAL;
     }
 
-    int active_width = GetWidthFromMetaData(output_handle);
-    int active_height = GetHeightFromMetaData(output_handle);
+    int active_width;
+    int active_height;
+
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, active_width,
+                                                          active_height);
 
     if ((active_width != INT(output_buffer_->width)) ||
         (active_height!= INT(output_buffer_->height)) ||
@@ -254,16 +250,32 @@
   output_buffer_->acquire_fence_fd = content_list->outbufAcquireFenceFd;
 
   if (output_handle) {
-    output_buffer_->format = GetSDMFormat(output_handle->format, output_handle->flags);
+    int output_handle_format = output_handle->format;
+
+    if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
+      output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
+    }
+
+    output_buffer_->format = GetSDMFormat(output_handle_format, output_handle->flags);
+
     if (output_buffer_->format == kFormatInvalid) {
       return -EINVAL;
     }
 
-    output_buffer_->width = GetWidthFromMetaData(output_handle);
-    output_buffer_->height = GetHeightFromMetaData(output_handle);
+    int output_buffer_width, output_buffer_height;
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, output_buffer_width,
+                                                          output_buffer_height);
+
+    output_buffer_->width = output_buffer_width;
+    output_buffer_->height = output_buffer_height;
     output_buffer_->flags.secure = 0;
     output_buffer_->flags.video = 0;
 
+    // TZ Protected Buffer - L1
+    if (output_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+      output_buffer_->flags.secure = 1;
+    }
+
     // ToDo: Need to extend for non-RGB formats
     output_buffer_->planes[0].fd = output_handle->fd;
     output_buffer_->planes[0].offset = output_handle->offset;
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 8fccf64..98444e1 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -91,7 +91,7 @@
   hwc_procs_default_.hotplug = Hotplug;
 
   hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
-  hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_4;
+  hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_5;
   hwc_composer_device_1_t::common.module = const_cast<hw_module_t*>(module);
   hwc_composer_device_1_t::common.close = Close;
   hwc_composer_device_1_t::prepare = Prepare;
@@ -570,8 +570,8 @@
   case qService::IQService::SET_VIEW_FRAME:
     break;
 
-  case qService::IQService::CONTROL_BACKLIGHT:
-    status = ControlBackLight(input_parcel);
+  case qService::IQService::TOGGLE_SCREEN_UPDATES:
+    status = ToggleScreenUpdates(input_parcel, output_parcel);
     break;
 
   case qService::IQService::QDCM_SVC_CMDS:
@@ -602,6 +602,14 @@
     status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
     break;
 
+  case qService::IQService::GET_PANEL_BRIGHTNESS:
+    status = GetPanelBrightness(input_parcel, output_parcel);
+    break;
+
+  case qService::IQService::SET_PANEL_BRIGHTNESS:
+    status = SetPanelBrightness(input_parcel, output_parcel);
+    break;
+
   default:
     DLOGW("QService command = %d is not supported", command);
     return -EINVAL;
@@ -610,43 +618,53 @@
   return status;
 }
 
-android::status_t HWCSession::ControlBackLight(const android::Parcel *input_parcel) {
-  uint32_t display_status = UINT32(input_parcel->readInt32());
-  HWCDisplay *display = hwc_display_[HWC_DISPLAY_PRIMARY];
+android::status_t HWCSession::ToggleScreenUpdates(const android::Parcel *input_parcel,
+                                                  android::Parcel *output_parcel) {
+  int input = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
 
-  DLOGI("Primary Display display_status = %d", display_status);
-
-  int fd = open("/sys/class/leds/lcd-backlight/brightness", O_RDWR);
-  const char *bl_brightness = "0";
-
-  if (fd < 0) {
-    DLOGE("unable to open brightness node err = %d errstr = %s", errno, strerror(errno));
-    return -1;
-  }
-
-  if (display_status == 0) {
-    // Read backlight and store it internally. Set backlight to 0 on primary.
-    if (read(fd, brightness_, sizeof(brightness_)) > 0) {
-      DLOGI("backlight brightness is %s", brightness_);
-      ssize_t ret = write(fd, bl_brightness, sizeof(bl_brightness));
-      if (ret < 0) {
-        DLOGE("Failed to write backlight node err = %d errstr = %s", errno, strerror(errno));
-        close(fd);
-        return -1;
-      }
-    }
-  } else {
-    // Restore backlight to original value.
-    ssize_t ret = write(fd, brightness_, sizeof(brightness_));
-    if (ret < 0) {
-      DLOGE("Failed to write backlight node err = %d errstr = %s", errno, strerror(errno));
-      close(fd);
-      return -1;
+  if (hwc_display_[HWC_DISPLAY_PRIMARY] && (input <= 1) && (input >= 0)) {
+    error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(input == 1);
+    if (error != 0) {
+      DLOGE("Failed to toggle screen updates = %d. Error = %d", input, error);
     }
   }
-  close(fd);
+  output_parcel->writeInt32(error);
 
-  return display->SetDisplayStatus(display_status);
+  return error;
+}
+
+android::status_t HWCSession::SetPanelBrightness(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel) {
+  int level = input_parcel->readInt32();
+  int error = android::BAD_VALUE;
+
+  if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(level);
+    if (error != 0) {
+      DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
+    }
+  }
+  output_parcel->writeInt32(error);
+
+  return error;
+}
+
+android::status_t HWCSession::GetPanelBrightness(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel) {
+  int error = android::BAD_VALUE;
+  int ret = error;
+
+  if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(&ret);
+    if (error != 0) {
+      ret = error;
+      DLOGE("Failed to get the panel brightness. Error = %d", error);
+    }
+  }
+  output_parcel->writeInt32(ret);
+
+  return error;
 }
 
 android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel,
diff --git a/sdm/libs/hwc/hwc_session.h b/sdm/libs/hwc/hwc_session.h
index e61e22d..22574dc 100644
--- a/sdm/libs/hwc/hwc_session.h
+++ b/sdm/libs/hwc/hwc_session.h
@@ -91,13 +91,18 @@
   android::status_t SetMaxMixerStages(const android::Parcel *input_parcel);
   android::status_t SetDisplayMode(const android::Parcel *input_parcel);
   android::status_t SetSecondaryDisplayStatus(const android::Parcel *input_parcel);
-  android::status_t ControlBackLight(const android::Parcel *input_parcel);
+  android::status_t ToggleScreenUpdates(const android::Parcel *input_parcel,
+                                        android::Parcel *output_parcel);
   android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
   android::status_t QdcmCMDHandler(const android::Parcel *input_parcel,
                                    android::Parcel *output_parcel);
   android::status_t ControlPartialUpdate(const android::Parcel *input_parcel, android::Parcel *out);
   android::status_t OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
-                                   android::Parcel *output_parcel);
+                                                   android::Parcel *output_parcel);
+  android::status_t SetPanelBrightness(const android::Parcel *input_parcel,
+                                       android::Parcel *output_parcel);
+  android::status_t GetPanelBrightness(const android::Parcel *input_parcel,
+                                       android::Parcel *output_parcel);
   // These functions return the actual display config info as opposed to FB
   android::status_t HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
                                                  android::Parcel *output_parcel);
@@ -119,7 +124,6 @@
   HWCBufferAllocator *buffer_allocator_ = NULL;
   HWCBufferSyncHandler *buffer_sync_handler_ = NULL;
   HWCColorManager *color_mgr_ = NULL;
-  char brightness_[64] = { 0 };
   static bool reset_panel_;
   bool secure_display_active_ = false;
 };
diff --git a/sdm/libs/utils/rect.cpp b/sdm/libs/utils/rect.cpp
index 64183ae..e120287 100644
--- a/sdm/libs/utils/rect.cpp
+++ b/sdm/libs/utils/rect.cpp
@@ -149,13 +149,14 @@
 }
 
 void SplitLeftRight(const LayerRect &in_rect, uint32_t split_count, uint32_t align_x,
-                   LayerRect *out_rects) {
+                    bool flip_horizontal, LayerRect *out_rects) {
   LayerRect rect_temp = in_rect;
 
   uint32_t split_width = UINT32(rect_temp.right - rect_temp.left) / split_count;
+  float aligned_width = FLOAT(CeilToMultipleOf(split_width, align_x));
 
   for (uint32_t count = 0; count < split_count; count++) {
-    float aligned_right = rect_temp.left + FLOAT(CeilToMultipleOf(split_width, align_x));
+    float aligned_right = rect_temp.left + aligned_width;
     out_rects[count].left = rect_temp.left;
     out_rects[count].right = MIN(rect_temp.right, aligned_right);
     out_rects[count].top = rect_temp.top;
@@ -165,16 +166,27 @@
 
     Log(kTagRotator, "SplitLeftRight", out_rects[count]);
   }
+
+  // If we have a horizontal flip, then we should be splitting the source from right to left
+  // to ensure that the right split will have an aligned width that matches the alignment on the
+  // destination.
+  if (flip_horizontal && split_count > 1) {
+    out_rects[0].right = out_rects[0].left + (out_rects[1].right - out_rects[1].left);
+    out_rects[1].left = out_rects[0].right;
+    Log(kTagRotator, "Adjusted Left", out_rects[0]);
+    Log(kTagRotator, "Adjusted Right", out_rects[1]);
+  }
 }
 
 void SplitTopBottom(const LayerRect &in_rect, uint32_t split_count, uint32_t align_y,
-                     LayerRect *out_rects) {
+                    bool flip_horizontal, LayerRect *out_rects) {
   LayerRect rect_temp = in_rect;
 
   uint32_t split_height = UINT32(rect_temp.bottom - rect_temp.top) / split_count;
+  float aligned_height = FLOAT(CeilToMultipleOf(split_height, align_y));
 
   for (uint32_t count = 0; count < split_count; count++) {
-    float aligned_bottom = rect_temp.top + FLOAT(CeilToMultipleOf(split_height, align_y));
+    float aligned_bottom = rect_temp.top + aligned_height;
     out_rects[count].top = rect_temp.top;
     out_rects[count].bottom = MIN(rect_temp.bottom, aligned_bottom);
     out_rects[count].left = rect_temp.left;
@@ -184,6 +196,16 @@
 
     Log(kTagRotator, "SplitTopBottom", out_rects[count]);
   }
+
+  // If we have a horizontal flip, then we should be splitting the destination from bottom to top
+  // to ensure that the bottom split's y-offset is aligned correctly after we swap the destinations
+  // while accounting for the flip.
+  if (flip_horizontal && split_count > 1) {
+    out_rects[0].bottom = out_rects[0].top + (out_rects[1].bottom - out_rects[1].top);
+    out_rects[1].top = out_rects[0].bottom;
+    Log(kTagRotator, "Adjusted Top", out_rects[0]);
+    Log(kTagRotator, "Adjusted Bottom", out_rects[1]);
+  }
 }
 
 }  // namespace sdm
diff --git a/sdm/libs/utils/sys.cpp b/sdm/libs/utils/sys.cpp
index dd62d6e..ff66fcf 100644
--- a/sdm/libs/utils/sys.cpp
+++ b/sdm/libs/utils/sys.cpp
@@ -38,6 +38,10 @@
 
 #ifndef SDM_VIRTUAL_DRIVER
 
+int PthreadCancel(pthread_t /* thread */) {
+  return 0;
+}
+
 // Pointer to actual driver interfaces.
 Sys::ioctl Sys::ioctl_ = ::ioctl;
 Sys::open Sys::open_ = ::open;
@@ -48,6 +52,8 @@
 Sys::fopen Sys::fopen_ = ::fopen;
 Sys::fclose Sys::fclose_ = ::fclose;
 Sys::getline Sys::getline_ = ::getline;
+Sys::pthread_cancel Sys::pthread_cancel_ = PthreadCancel;
+Sys::dup Sys::dup_ = ::dup;
 
 #else
 
@@ -61,6 +67,7 @@
 extern FILE* virtual_fopen(const char *fname, const char *mode);
 extern int virtual_fclose(FILE* fileptr);
 extern ssize_t virtual_getline(char **lineptr, size_t *linelen, FILE *stream);
+extern int virtual_dup(int fd);
 
 Sys::ioctl Sys::ioctl_ = virtual_ioctl;
 Sys::open Sys::open_ = virtual_open;
@@ -71,6 +78,8 @@
 Sys::fopen Sys::fopen_ = virtual_fopen;
 Sys::fclose Sys::fclose_ = virtual_fclose;
 Sys::getline Sys::getline_ = virtual_getline;
+Sys::pthread_cancel Sys::pthread_cancel_ = ::pthread_cancel;
+Sys::dup Sys::dup_ = virtual_dup;
 
 #endif  // SDM_VIRTUAL_DRIVER