Merge "sdm: Signal to handle SIGPIPE"
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 87f7bcf..1727818 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -292,6 +292,12 @@
    *      uint32_t - FB Secure mode
    */
   CONNECTOR_SET_FB_SECURE_MODE,
+  /*
+   * Op: Sets a crtc id to this connector
+   * Arg: uint32_t - Connector ID
+   *      uint32_t - CRTC ID
+   */
+  CONNECTOR_SET_CRTC,
 };
 
 enum struct DRMRotation {
diff --git a/libgralloc1/gr_adreno_info.cpp b/libgralloc1/gr_adreno_info.cpp
index f71f1d2..1ac99be 100644
--- a/libgralloc1/gr_adreno_info.cpp
+++ b/libgralloc1/gr_adreno_info.cpp
@@ -212,6 +212,8 @@
        return ADRENO_PIXELFORMAT_R10G10B10X2_UNORM;
     case HAL_PIXEL_FORMAT_ABGR_2101010:
        return ADRENO_PIXELFORMAT_A2B10G10R10_UNORM;
+    case HAL_PIXEL_FORMAT_RGBA_FP16:
+       return ADRENO_PIXELFORMAT_R16G16B16A16_FLOAT;
     default:
       ALOGE("%s: No map for format: 0x%x", __FUNCTION__, hal_format);
       break;
diff --git a/libgralloc1/gr_adreno_info.h b/libgralloc1/gr_adreno_info.h
index b19256a..83966ae 100644
--- a/libgralloc1/gr_adreno_info.h
+++ b/libgralloc1/gr_adreno_info.h
@@ -37,6 +37,7 @@
 // Adreno Pixel Formats
 typedef enum {
   ADRENO_PIXELFORMAT_UNKNOWN = 0,
+  ADRENO_PIXELFORMAT_R16G16B16A16_FLOAT = 10,
   ADRENO_PIXELFORMAT_R10G10B10A2_UNORM = 24,  // Vertex, Normalized GL_UNSIGNED_INT_10_10_10_2_OES
   ADRENO_PIXELFORMAT_R8G8B8A8 = 28,
   ADRENO_PIXELFORMAT_R8G8B8A8_SRGB = 29,
@@ -66,7 +67,7 @@
   ADRENO_PIXELFORMAT_NV21 = 619,
   ADRENO_PIXELFORMAT_Y8U8V8A8 = 620,  // YUV 4:4:4 packed (1 plane)
   ADRENO_PIXELFORMAT_Y8 = 625,        //  Single 8-bit luma only channel YUV format
-  ADRENO_PIXELFORMAT_TP10 = 648,      // YUV 4:2:0 planar 10 bits/comp (2 planes)
+  ADRENO_PIXELFORMAT_TP10 = 654,      // YUV 4:2:0 planar 10 bits/comp (2 planes)
 } ADRENOPIXELFORMAT;
 
 class AdrenoMemInfo {
diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp
index eb97f15..cd89d41 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -681,6 +681,7 @@
             *color_space = HAL_CSC_ITU_R_709;
             break;
           case ColorPrimaries_BT601_6_525:
+          case ColorPrimaries_BT601_6_625:
             *color_space = ((color_metadata.range) ? HAL_CSC_ITU_R_601_FR : HAL_CSC_ITU_R_601);
             break;
           case ColorPrimaries_BT2020:
@@ -831,6 +832,9 @@
     case HAL_PIXEL_FORMAT_RAW10:
     case HAL_PIXEL_FORMAT_YV12:
     case HAL_PIXEL_FORMAT_Y8:
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+    case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+    case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
       return true;
     default:
       return false;
diff --git a/sdm/libs/core/Android.mk b/sdm/libs/core/Android.mk
index bb3b71d..aba66c6 100644
--- a/sdm/libs/core/Android.mk
+++ b/sdm/libs/core/Android.mk
@@ -49,6 +49,7 @@
 ifneq ($(TARGET_IS_HEADLESS), true)
     LOCAL_SRC_FILES           += $(LOCAL_HW_INTF_PATH_2)/hw_info_drm.cpp \
                                  $(LOCAL_HW_INTF_PATH_2)/hw_device_drm.cpp \
+                                 $(LOCAL_HW_INTF_PATH_2)/hw_peripheral_drm.cpp \
                                  $(LOCAL_HW_INTF_PATH_2)/hw_tv_drm.cpp \
                                  $(LOCAL_HW_INTF_PATH_2)/hw_events_drm.cpp \
                                  $(LOCAL_HW_INTF_PATH_2)/hw_scale_drm.cpp \
diff --git a/sdm/libs/core/color_manager.cpp b/sdm/libs/core/color_manager.cpp
index 938ab99..4c33a25 100644
--- a/sdm/libs/core/color_manager.cpp
+++ b/sdm/libs/core/color_manager.cpp
@@ -180,6 +180,12 @@
 }
 
 DisplayError ColorManagerProxy::Commit() {
+  static bool first_cycle = true;
+  if (first_cycle) {
+    first_cycle = false;
+    return kErrorNone;
+  }
+
   Locker &locker(pp_features_.GetLocker());
   SCOPE_LOCK(locker);
 
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 612be9b..34740a9 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -1062,9 +1062,9 @@
   if (error != kErrorNone) {
     return error;
   }
-  if (mixer_attributes != mixer_attributes_) {
-    DisablePartialUpdateOneFrame();
-  }
+
+  // Disable partial update for one frame on any display changes
+  DisablePartialUpdateOneFrame();
 
   display_attributes_ = display_attributes;
   mixer_attributes_ = mixer_attributes;
diff --git a/sdm/libs/core/display_virtual.cpp b/sdm/libs/core/display_virtual.cpp
index fcdc152..dfe4fd3 100644
--- a/sdm/libs/core/display_virtual.cpp
+++ b/sdm/libs/core/display_virtual.cpp
@@ -24,7 +24,7 @@
 
 #include <utils/constants.h>
 #include <utils/debug.h>
-
+#include <algorithm>
 #include "display_virtual.h"
 #include "hw_interface.h"
 #include "hw_info_interface.h"
@@ -49,11 +49,25 @@
     return error;
   }
 
-  hw_intf_->GetDisplayAttributes(0 /* active_index */, &display_attributes_);
+  HWScaleLutInfo lut_info = {};
+  error = comp_manager_->GetScaleLutConfig(&lut_info);
+  if (error == kErrorNone) {
+    error = hw_intf_->SetScaleLutConfig(&lut_info);
+    if (error != kErrorNone) {
+      HWInterface::Destroy(hw_intf_);
+      return error;
+    }
+  }
 
-  error = DisplayBase::Init();
-  if (error != kErrorNone) {
-    HWInterface::Destroy(hw_intf_);
+  if (hw_info_intf_) {
+    HWResourceInfo hw_resource_info = HWResourceInfo();
+    hw_info_intf_->GetHWResourceInfo(&hw_resource_info);
+    auto max_mixer_stages = hw_resource_info.num_blending_stages;
+    int property_value = Debug::GetMaxPipesPerMixer(display_type_);
+    if (property_value >= 0) {
+      max_mixer_stages = std::min(UINT32(property_value), hw_resource_info.num_blending_stages);
+    }
+    DisplayBase::SetMaxMixerStages(max_mixer_stages);
   }
 
   return error;
@@ -87,6 +101,8 @@
   DisplayError error = kErrorNone;
   HWDisplayAttributes display_attributes;
   HWMixerAttributes mixer_attributes;
+  HWPanelInfo hw_panel_info = {};
+  DisplayConfigVariableInfo fb_config = fb_config_;
 
   display_attributes.x_pixels = variable_info->x_pixels;
   display_attributes.y_pixels = variable_info->y_pixels;
@@ -101,25 +117,34 @@
     return error;
   }
 
+  hw_intf_->GetHWPanelInfo(&hw_panel_info);
+
   error = hw_intf_->GetMixerAttributes(&mixer_attributes);
   if (error != kErrorNone) {
     return error;
   }
 
+  // fb_config will be updated only once after creation of virtual display
+  if (fb_config.x_pixels == 0 || fb_config.y_pixels == 0) {
+    fb_config = display_attributes;
+  }
+
   // if display is already connected, unregister display from composition manager and register
   // the display with new configuration.
   if (display_comp_ctx_) {
     comp_manager_->UnregisterDisplay(display_comp_ctx_);
   }
 
-  error = comp_manager_->RegisterDisplay(display_type_, display_attributes, hw_panel_info_,
-                                         mixer_attributes, fb_config_, &display_comp_ctx_);
+  error = comp_manager_->RegisterDisplay(display_type_, display_attributes, hw_panel_info,
+                                         mixer_attributes, fb_config, &display_comp_ctx_);
   if (error != kErrorNone) {
     return error;
   }
 
   display_attributes_ = display_attributes;
   mixer_attributes_ = mixer_attributes;
+  hw_panel_info_ = hw_panel_info;
+  fb_config_ = fb_config;
 
   DLOGI("Virtual display resolution changed to[%dx%d]", display_attributes_.x_pixels,
         display_attributes_.y_pixels);
diff --git a/sdm/libs/core/display_virtual.h b/sdm/libs/core/display_virtual.h
index 185366c..f9cc737 100644
--- a/sdm/libs/core/display_virtual.h
+++ b/sdm/libs/core/display_virtual.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -56,9 +56,6 @@
   virtual DisplayError SetRefreshRate(uint32_t refresh_rate, bool final_rate) {
     return kErrorNotSupported;
   }
-  virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height) {
-    return kErrorNotSupported;
-  }
   virtual DisplayError SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data) {
     return kErrorNotSupported;
   }
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index d530052..4c7136e 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -329,8 +329,6 @@
                          HWInfoInterface *hw_info_intf)
     : hw_info_intf_(hw_info_intf), buffer_sync_handler_(buffer_sync_handler),
       registry_(buffer_allocator) {
-  disp_type_ = DRMDisplayType::PERIPHERAL;
-  device_name_ = "Peripheral Display";
   hw_info_intf_ = hw_info_intf;
 }
 
@@ -346,36 +344,19 @@
       DLOGE("RegisterDisplay failed for %s", device_name_);
       return kErrorResources;
     }
+
     drm_mgr_intf_->CreateAtomicReq(token_, &drm_atomic_intf_);
     drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
-    // Commit to setup pipeline with mode, which then tells us the topology etc
-    if (!deferred_initialize_) {
-      drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id,
-                                &connector_info_.modes[current_mode_index_]);
-      drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
-      if (drm_atomic_intf_->Commit(true /* synchronous */, false /* retain_planes*/)) {
-        DRM_LOGI("Setting up CRTC %d, Connector %d for %s failed", token_.crtc_id,
-          token_.conn_id, device_name_);
-        return kErrorResources;
-      }
-      // Reload connector info for updated info after 1st commit
-      drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
-    }
-    InitializeConfigs();
   } else {
     display_attributes_.push_back(HWDisplayAttributes());
     PopulateDisplayAttributes(current_mode_index_);
   }
-  PopulateHWPanelInfo();
-  UpdateMixerAttributes();
 
   hw_info_intf_->GetHWResourceInfo(&hw_resource_);
-
   // TODO(user): In future, remove has_qseed3 member, add version and pass version to constructor
   if (hw_resource_.has_qseed3) {
     hw_scale_ = new HWScaleDRM(HWScaleDRM::Version::V2);
   }
-  scalar_data_.resize(hw_resource_.hw_dest_scalar_info.count);
   return kErrorNone;
 }
 
@@ -493,7 +474,12 @@
   snprintf(hw_panel_info_.panel_name, sizeof(hw_panel_info_.panel_name), "%s",
            connector_info_.panel_name.c_str());
 
-  UpdatePanelSplitInfo();
+  uint32_t index = current_mode_index_;
+  hw_panel_info_.split_info.left_split = display_attributes_[index].x_pixels;
+  if (display_attributes_[index].is_device_split) {
+    hw_panel_info_.split_info.left_split = hw_panel_info_.split_info.right_split =
+        display_attributes_[index].x_pixels / 2;
+  }
 
   hw_panel_info_.partial_update = connector_info_.num_roi;
   hw_panel_info_.left_roi_count = UINT32(connector_info_.num_roi);
@@ -681,14 +667,13 @@
     DLOGE("Invalid mode index %d mode size %d", index, UINT32(display_attributes_.size()));
     return kErrorParameters;
   }
-
   current_mode_index_ = index;
-  UpdatePanelSplitInfo();
+  // TODO(user): Topology/panel roi alignment information will be updated as a part of next commit
+  // which is too late for the requested mode that has different panel alignments. So driver needs
+  // to update panel/topology information for all modes during probe to reslove this issue.
+  PopulateHWPanelInfo();
   UpdateMixerAttributes();
-
-  DLOGI("Setting mode index %d for CRTC %d, Connector %d display %s is successful", index,
-         token_.crtc_id, token_.conn_id, device_name_);
-
+  switch_mode_ = true;
   return kErrorNone;
 }
 
@@ -714,6 +699,7 @@
     DLOGE("Failed with error: %d", ret);
     return kErrorHardware;
   }
+
   return kErrorNone;
 }
 
@@ -731,6 +717,7 @@
     DLOGE("Failed with error: %d", ret);
     return kErrorHardware;
   }
+
   return kErrorNone;
 }
 
@@ -929,7 +916,6 @@
     drm_atomic_intf_->Perform(DRMOps::CRTC_SET_IDLE_TIMEOUT, token_.crtc_id,
                               hw_layer_info.set_idle_time_ms);
   }
-  SetDestScalarData(hw_layer_info);
 }
 
 void HWDeviceDRM::AddSolidfillStage(const HWSolidfillStage &sf, uint32_t plane_alpha) {
@@ -974,7 +960,7 @@
 
   int ret = drm_atomic_intf_->Validate();
   if (ret) {
-    DLOGE("%s failed with error %d", __FUNCTION__, ret);
+    DLOGE("failed with error %d for %s", ret, device_name_);
     vrefresh_ = 0;
     return kErrorHardware;
   }
@@ -1095,6 +1081,13 @@
     vrefresh_ = 0;
   }
 
+  if (switch_mode_) {
+    // Reload connector info for updated info after 1st commit
+    drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
+    PopulateHWPanelInfo();
+    switch_mode_ = false;
+  }
+
   return kErrorNone;
 }
 
@@ -1106,7 +1099,6 @@
     return kErrorHardware;
   }
 
-  ResetDisplayParams();
   return kErrorNone;
 }
 
@@ -1202,13 +1194,6 @@
   return true;
 }
 
-void HWDeviceDRM::ResetDisplayParams() {
-  sde_dest_scalar_data_ = {};
-  for (uint32_t j = 0; j < scalar_data_.size(); j++) {
-    scalar_data_[j] = {};
-  }
-}
-
 DisplayError HWDeviceDRM::SetCursorPosition(HWLayers *hw_layers, int x, int y) {
   DTRACE_SCOPED();
   return kErrorNone;
@@ -1469,6 +1454,7 @@
   mixer_attributes_.split_left = display_attributes_[index].is_device_split
                                      ? hw_panel_info_.split_info.left_split
                                      : mixer_attributes_.width;
+  DLOGI("Mixer WxH %dx%d for %s", mixer_attributes_.width, mixer_attributes_.height, device_name_);
 }
 
 void HWDeviceDRM::SetSecureConfig(const LayerBuffer &input_buffer, DRMSecureMode *fb_secure_mode,
@@ -1497,15 +1483,6 @@
   }
 }
 
-void HWDeviceDRM::UpdatePanelSplitInfo() {
-  uint32_t index = current_mode_index_;
-  hw_panel_info_.split_info.left_split = display_attributes_[index].x_pixels;
-  if (display_attributes_[index].is_device_split) {
-    hw_panel_info_.split_info.left_split = hw_panel_info_.split_info.right_split =
-        display_attributes_[index].x_pixels / 2;
-  }
-}
-
 void HWDeviceDRM::SetTopology(sde_drm::DRMTopology drm_topology, HWTopology *hw_topology) {
   switch (drm_topology) {
     case DRMTopology::SINGLE_LM:          *hw_topology = kSingleLM;        break;
@@ -1520,45 +1497,4 @@
   }
 }
 
-void HWDeviceDRM::SetDestScalarData(HWLayersInfo hw_layer_info) {
-  if (!hw_resource_.hw_dest_scalar_info.count) {
-    return;
-  }
-
-  uint32_t index = 0;
-  for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
-    DestScaleInfoMap::iterator it = hw_layer_info.dest_scale_info_map.find(i);
-
-    if (it == hw_layer_info.dest_scale_info_map.end()) {
-      continue;
-    }
-
-    HWDestScaleInfo *dest_scale_info = it->second;
-    SDEScaler *scale = &scalar_data_[index];
-    hw_scale_->SetScaler(dest_scale_info->scale_data, scale);
-    sde_drm_dest_scaler_cfg *dest_scalar_data = &sde_dest_scalar_data_.ds_cfg[index];
-    dest_scalar_data->flags = 0;
-    if (scale->scaler_v2.enable) {
-      dest_scalar_data->flags |= SDE_DRM_DESTSCALER_ENABLE;
-    }
-    if (scale->scaler_v2.de.enable) {
-      dest_scalar_data->flags |= SDE_DRM_DESTSCALER_ENHANCER_UPDATE;
-    }
-    if (dest_scale_info->scale_update) {
-      dest_scalar_data->flags |= SDE_DRM_DESTSCALER_SCALE_UPDATE;
-    }
-    dest_scalar_data->index = i;
-    dest_scalar_data->lm_width = dest_scale_info->mixer_width;
-    dest_scalar_data->lm_height = dest_scale_info->mixer_height;
-    dest_scalar_data->scaler_cfg = reinterpret_cast<uint64_t>(&scale->scaler_v2);
-    if (hw_panel_info_.partial_update) {
-      dest_scalar_data->flags |= SDE_DRM_DESTSCALER_PU_ENABLE;
-    }
-    index++;
-  }
-  sde_dest_scalar_data_.num_dest_scaler = UINT32(hw_layer_info.dest_scale_info_map.size());
-  drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DEST_SCALER_CONFIG, token_.crtc_id,
-                            reinterpret_cast<uint64_t>(&sde_dest_scalar_data_));
-}
-
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 67646df..0a8b722 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -116,7 +116,6 @@
   void PopulateHWPanelInfo();
   void GetHWDisplayPortAndMode();
   void GetHWPanelMaxBrightness();
-  void ResetDisplayParams();
   bool EnableHotPlugDetection(int enable);
   void UpdateMixerAttributes();
   void SetSolidfillStages();
@@ -132,7 +131,6 @@
   void SetSecureConfig(const LayerBuffer &input_buffer, sde_drm::DRMSecureMode *fb_secure_mode,
                        sde_drm::DRMSecurityLevel *security_level);
   bool IsResolutionSwitchEnabled() const { return resolution_switch_enabled_; }
-  void UpdatePanelSplitInfo();
   void SetTopology(sde_drm::DRMTopology drm_topology, HWTopology *hw_topology);
 
   class Registry {
@@ -161,7 +159,6 @@
 
  protected:
   const char *device_name_ = {};
-  bool deferred_initialize_ = false;
   bool default_mode_ = false;
   sde_drm::DRMDisplayType disp_type_ = {};
   HWInfoInterface *hw_info_intf_ = {};
@@ -177,17 +174,16 @@
   std::vector<HWDisplayAttributes> display_attributes_ = {};
   uint32_t current_mode_index_ = 0;
   sde_drm::DRMConnectorInfo connector_info_ = {};
+  bool first_cycle_ = true;
 
  private:
-  void SetDestScalarData(HWLayersInfo hw_layer_info);
   bool synchronous_commit_ = false;
   HWMixerAttributes mixer_attributes_ = {};
   std::string interface_str_ = "DSI";
   std::vector<sde_drm::DRMSolidfillStage> solid_fills_ {};
   bool resolution_switch_enabled_ = false;
   uint32_t vrefresh_ = 0;
-  sde_drm_dest_scaler_data sde_dest_scalar_data_ = {};
-  std::vector<SDEScaler> scalar_data_ = {};
+  bool switch_mode_ = false;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index 626cb40..88e4efa 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -197,7 +197,7 @@
   hw_resource->hw_revision = 0;
 
   // TODO(user): Deprecate
-  hw_resource->max_mixer_width = 0;
+  hw_resource->max_mixer_width = 2560;
   hw_resource->writeback_index = 0;
   hw_resource->has_bwc = false;
   hw_resource->has_ubwc = true;
@@ -242,7 +242,7 @@
   DLOGI("\tLinear = %d", hw_resource->linear_factor);
   DLOGI("\tScale = %d", hw_resource->scale_factor);
   DLOGI("\tFudge_factor = %d", hw_resource->extra_fudge_factor);
-  DLOGI("\tib_fudge_factor = %d", hw_resource->ib_fudge_factor);
+  DLOGI("\tib_fudge_factor = %f", hw_resource->ib_fudge_factor);
 
   if (hw_resource->separate_rotator || hw_resource->num_dma_pipe) {
     GetHWRotatorInfo(hw_resource);
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
new file mode 100644
index 0000000..92669e1
--- /dev/null
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -0,0 +1,170 @@
+/*
+Copyright (c) 2017, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/debug.h>
+
+#include "hw_peripheral_drm.h"
+
+#define __CLASS__ "HWPeripheralDRM"
+
+using sde_drm::DRMDisplayType;
+using sde_drm::DRMOps;
+using sde_drm::DRMTopology;
+using sde_drm::DRMPowerMode;
+
+namespace sdm {
+
+HWPeripheralDRM::HWPeripheralDRM(BufferSyncHandler *buffer_sync_handler,
+                                 BufferAllocator *buffer_allocator,
+                                 HWInfoInterface *hw_info_intf)
+  : HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf) {
+  disp_type_ = DRMDisplayType::PERIPHERAL;
+  device_name_ = "Peripheral Display";
+}
+
+DisplayError HWPeripheralDRM::Init() {
+  DisplayError ret = HWDeviceDRM::Init();
+  if (ret != kErrorNone) {
+    DLOGE("Init failed for %s", device_name_);
+    return ret;
+  }
+
+  scalar_data_.resize(hw_resource_.hw_dest_scalar_info.count);
+
+  if (connector_info_.topology == DRMTopology::UNKNOWN) {
+    connector_info_.topology = DRMTopology::DUAL_LM;
+  }
+
+  InitializeConfigs();
+  PopulateHWPanelInfo();
+  UpdateMixerAttributes();
+
+  return kErrorNone;
+}
+
+DisplayError HWPeripheralDRM::Validate(HWLayers *hw_layers) {
+  // Hijack the first validate to setup pipeline. This is a stopgap solution
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  if (first_cycle_) {
+    drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, token_.conn_id, token_.crtc_id);
+    drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::ON);
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id,
+                              &connector_info_.modes[current_mode_index_]);
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
+    if (drm_atomic_intf_->Commit(true /* synchronous */, false /* retain pipes*/)) {
+      DLOGE("Setting up CRTC %d, Connector %d for %s failed",
+            token_.crtc_id, token_.conn_id, device_name_);
+      return kErrorResources;
+    }
+    // Reload connector info for updated info after 1st commit
+    drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
+    PopulateDisplayAttributes(current_mode_index_);
+    PopulateHWPanelInfo();
+    first_cycle_ = false;
+  }
+  SetDestScalarData(hw_layer_info);
+
+  return HWDeviceDRM::Validate(hw_layers);
+}
+
+DisplayError HWPeripheralDRM::Commit(HWLayers *hw_layers) {
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  SetDestScalarData(hw_layer_info);
+
+  return HWDeviceDRM::Commit(hw_layers);
+}
+
+DisplayError HWPeripheralDRM::PowerOn() {
+  if (first_cycle_) {
+    return kErrorNone;
+  }
+
+  return HWDeviceDRM::PowerOn();
+}
+
+void HWPeripheralDRM::ResetDisplayParams() {
+  sde_dest_scalar_data_ = {};
+  for (uint32_t j = 0; j < scalar_data_.size(); j++) {
+    scalar_data_[j] = {};
+  }
+}
+
+void HWPeripheralDRM::SetDestScalarData(HWLayersInfo hw_layer_info) {
+  if (!hw_resource_.hw_dest_scalar_info.count) {
+    return;
+  }
+
+  uint32_t index = 0;
+  for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
+    DestScaleInfoMap::iterator it = hw_layer_info.dest_scale_info_map.find(i);
+
+    if (it == hw_layer_info.dest_scale_info_map.end()) {
+      continue;
+    }
+
+    HWDestScaleInfo *dest_scale_info = it->second;
+    SDEScaler *scale = &scalar_data_[index];
+    hw_scale_->SetScaler(dest_scale_info->scale_data, scale);
+    sde_drm_dest_scaler_cfg *dest_scalar_data = &sde_dest_scalar_data_.ds_cfg[index];
+    dest_scalar_data->flags = 0;
+    if (scale->scaler_v2.enable) {
+      dest_scalar_data->flags |= SDE_DRM_DESTSCALER_ENABLE;
+    }
+    if (scale->scaler_v2.de.enable) {
+      dest_scalar_data->flags |= SDE_DRM_DESTSCALER_ENHANCER_UPDATE;
+    }
+    if (dest_scale_info->scale_update) {
+      dest_scalar_data->flags |= SDE_DRM_DESTSCALER_SCALE_UPDATE;
+    }
+    dest_scalar_data->index = i;
+    dest_scalar_data->lm_width = dest_scale_info->mixer_width;
+    dest_scalar_data->lm_height = dest_scale_info->mixer_height;
+    dest_scalar_data->scaler_cfg = reinterpret_cast<uint64_t>(&scale->scaler_v2);
+    if (hw_panel_info_.partial_update) {
+      dest_scalar_data->flags |= SDE_DRM_DESTSCALER_PU_ENABLE;
+    }
+    index++;
+  }
+  sde_dest_scalar_data_.num_dest_scaler = UINT32(hw_layer_info.dest_scale_info_map.size());
+  drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DEST_SCALER_CONFIG, token_.crtc_id,
+                            reinterpret_cast<uint64_t>(&sde_dest_scalar_data_));
+}
+
+DisplayError HWPeripheralDRM::Flush() {
+  DisplayError err = HWDeviceDRM::Flush();
+  if (err != kErrorNone) {
+    return err;
+  }
+
+  ResetDisplayParams();
+  return kErrorNone;
+}
+
+
+}  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.h b/sdm/libs/core/drm/hw_peripheral_drm.h
new file mode 100644
index 0000000..0b596ad
--- /dev/null
+++ b/sdm/libs/core/drm/hw_peripheral_drm.h
@@ -0,0 +1,60 @@
+/*
+Copyright (c) 2017, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_PERIPHERAL_DRM_H__
+#define __HW_PERIPHERAL_DRM_H__
+
+#include <vector>
+#include "hw_device_drm.h"
+
+namespace sdm {
+
+class HWPeripheralDRM : public HWDeviceDRM {
+ public:
+  explicit HWPeripheralDRM(BufferSyncHandler *buffer_sync_handler,
+                           BufferAllocator *buffer_allocator,
+                           HWInfoInterface *hw_info_intf);
+  virtual ~HWPeripheralDRM() {}
+
+ protected:
+  virtual DisplayError Init();
+  virtual DisplayError Validate(HWLayers *hw_layers);
+  virtual DisplayError Commit(HWLayers *hw_layers);
+  virtual DisplayError PowerOn();
+  virtual DisplayError Flush();
+ private:
+  void SetDestScalarData(HWLayersInfo hw_layer_info);
+  void ResetDisplayParams();
+  sde_drm_dest_scaler_data sde_dest_scalar_data_ = {};
+  std::vector<SDEScaler> scalar_data_ = {};
+};
+
+}  // namespace sdm
+
+#endif  // __HW_PERIPHERAL_DRM_H__
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index bd9ddc2..e93f065 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -67,35 +67,14 @@
   device_name_ = "TV Display Device";
 }
 
-// TODO(user) : split function in base class and avoid code duplicacy
-// by using base implementation for this basic stuff
 DisplayError HWTVDRM::Init() {
-  DisplayError error = kErrorNone;
-
-  default_mode_ = (DRMLibLoader::GetInstance()->IsLoaded() == false);
-
-  if (!default_mode_) {
-    DRMMaster *drm_master = {};
-    int dev_fd = -1;
-    DRMMaster::GetInstance(&drm_master);
-    drm_master->GetHandle(&dev_fd);
-    DRMLibLoader::GetInstance()->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_);
-    if (drm_mgr_intf_->RegisterDisplay(DRMDisplayType::TV, &token_)) {
-      DLOGE("RegisterDisplay failed");
-      return kErrorResources;
-    }
-
-    drm_mgr_intf_->CreateAtomicReq(token_, &drm_atomic_intf_);
-    drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
-    InitializeConfigs();
+  DisplayError error = HWDeviceDRM::Init();
+  if (error != kErrorNone) {
+    DLOGE("Init failed for %s", device_name_);
+    return error;
   }
 
-  hw_info_intf_->GetHWResourceInfo(&hw_resource_);
-
-  // TODO(user): In future, remove has_qseed3 member, add version and pass version to constructor
-  if (hw_resource_.has_qseed3) {
-    hw_scale_ = new HWScaleDRM(HWScaleDRM::Version::V2);
-  }
+  InitializeConfigs();
 
   return error;
 }
@@ -106,6 +85,10 @@
     return kErrorNotSupported;
   }
 
+  if (first_cycle_) {
+    drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, token_.conn_id, token_.crtc_id);
+  }
+
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, &connector_info_.modes[index]);
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
 
@@ -116,15 +99,16 @@
     return kErrorResources;
   }
 
-  // Reload connector info for updated info after 1st commit and validate
+  DLOGI("Setup CRTC %d, Connector %d for %s", token_.crtc_id, token_.conn_id, device_name_);
+  first_cycle_ = false;
+
+  // Reload connector info for updated info after 1st commit
   drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
   if (index >= connector_info_.modes.size()) {
     DLOGE("Invalid mode index %d mode size %d", index, UINT32(connector_info_.modes.size()));
     return kErrorNotSupported;
   }
 
-  DLOGI("Setup CRTC %d, Connector %d for %s", token_.crtc_id, token_.conn_id, device_name_);
-
   current_mode_index_ = index;
   PopulateDisplayAttributes(index);
   PopulateHWPanelInfo();
diff --git a/sdm/libs/core/drm/hw_virtual_drm.cpp b/sdm/libs/core/drm/hw_virtual_drm.cpp
index 176d4ec..626beea 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.cpp
+++ b/sdm/libs/core/drm/hw_virtual_drm.cpp
@@ -31,6 +31,8 @@
 #include <ctype.h>
 #include <drm_logger.h>
 #include <utils/debug.h>
+#include <algorithm>
+#include <vector>
 #include "hw_device_drm.h"
 #include "hw_virtual_drm.h"
 #include "hw_info_drm.h"
@@ -49,24 +51,28 @@
                            BufferAllocator *buffer_allocator,
                            HWInfoInterface *hw_info_intf)
                            : HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf) {
-  HWDeviceDRM::deferred_initialize_ = true;
   HWDeviceDRM::device_name_ = "Virtual Display Device";
-  HWDeviceDRM::hw_info_intf_ = hw_info_intf;
   HWDeviceDRM::disp_type_ = DRMDisplayType::VIRTUAL;
 }
 
 DisplayError HWVirtualDRM::Init() {
-  display_attributes_.push_back(HWDisplayAttributes());
-  return kErrorNone;
-}
-
-DisplayError HWVirtualDRM::DeferredInit() {
-  if (HWDeviceDRM::Init() != kErrorNone)
-    return kErrorResources;
-
-  drm_mgr_intf_->SetScalerLUT(drm_lut_info_);
-  DLOGI_IF(kTagDriverConfig, "Setup CRTC %d, Connector %d for %s",
-            token_.crtc_id, token_.conn_id, device_name_);
+  DisplayError err = HWDeviceDRM::Init();
+  if (err != kErrorNone) {
+    return err;
+  }
+  // TODO(user): Remove this code once driver populates appropriate topology based on virtual
+  // display configuration
+  if (connector_info_.topology == sde_drm::DRMTopology::UNKNOWN) {
+    uint32_t max_width = 0;
+    for (uint32_t i = 0; i < (uint32_t)connector_info_.modes.size(); i++) {
+      max_width = std::max(max_width, UINT32(connector_info_.modes[i].hdisplay));
+    }
+    connector_info_.topology = sde_drm::DRMTopology::SINGLE_LM;
+    if (max_width > hw_resource_.max_mixer_width) {
+      connector_info_.topology = sde_drm::DRMTopology::DUAL_LM_MERGE;
+    }
+  }
+  InitializeConfigs();
 
   return kErrorNone;
 }
@@ -79,9 +85,9 @@
 void HWVirtualDRM::ConfigureWbConnectorDestRect() {
   DRMRect dst = {};
   dst.left = 0;
-  dst.bottom = height_;
+  dst.bottom = display_attributes_[current_mode_index_].y_pixels;
   dst.top = 0;
-  dst.right = width_;
+  dst.right = display_attributes_[current_mode_index_].x_pixels;
   drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_OUTPUT_RECT, token_.conn_id, dst);
   return;
 }
@@ -92,51 +98,66 @@
 }
 
 void HWVirtualDRM::InitializeConfigs() {
-  drmModeModeInfo mode = {};
-  mode.hdisplay = mode.hsync_start = mode.hsync_end = mode.htotal = (uint16_t) width_;
-  mode.vdisplay = mode.vsync_start = mode.vsync_end = mode.vtotal = (uint16_t) height_;
-  // Not sure SF has a way to configure refresh rate. Hardcoding to 60 fps for now.
-  // TODO(user): Make this configurable.
-  mode.vrefresh = 60;
-  mode.clock = (mode.htotal * mode.vtotal * mode.vrefresh) / 1000;
-
-  struct sde_drm_wb_cfg wb_cfg;
-  wb_cfg.connector_id = token_.conn_id;
-  wb_cfg.flags |= SDE_DRM_WB_CFG_FLAGS_CONNECTED;
-  wb_cfg.count_modes = 1;
-  wb_cfg.modes = (uint64_t)&mode;
-  #ifdef DRM_IOCTL_SDE_WB_CONFIG
-  int ret = drmIoctl(dev_fd_, DRM_IOCTL_SDE_WB_CONFIG, &wb_cfg);
-  #endif
-  if (ret) {
-    DLOGE("WB config failed\n");
-  } else {
-    drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
-    DumpConfigs();
+  display_attributes_.resize(connector_info_.modes.size());
+  for (uint32_t i = 0; i < connector_info_.modes.size(); i++) {
+    PopulateDisplayAttributes(i);
   }
-
-  // TODO(user): Remove this code once driver populates appropriate topology based on virtual
-  // display configuration
-  if (connector_info_.topology == sde_drm::DRMTopology::UNKNOWN) {
-    connector_info_.topology = sde_drm::DRMTopology::SINGLE_LM;
-    if (width_ > hw_resource_.max_mixer_width) {
-      connector_info_.topology = sde_drm::DRMTopology::DUAL_LM_MERGE;
-    }
-  }
-  PopulateDisplayAttributes(current_mode_index_);
 }
 
-void HWVirtualDRM::DumpConfigs() {
+DisplayError HWVirtualDRM::SetWbConfigs(const HWDisplayAttributes &display_attributes) {
+  int ret = -EINVAL;
+  int mode_index = -1;
+  // Add new connector mode to the list
+  drmModeModeInfo mode = {};
+  mode.hdisplay = mode.hsync_start = mode.hsync_end = mode.htotal =
+                                       UINT16(display_attributes.x_pixels);
+  mode.vdisplay = mode.vsync_start = mode.vsync_end = mode.vtotal =
+                                       UINT16(display_attributes.y_pixels);
+  mode.vrefresh = UINT32(display_attributes.fps);
+  mode.clock = (mode.htotal * mode.vtotal * mode.vrefresh) / 1000;
+  connector_info_.modes.push_back(mode);
+
+  // Inform the updated mode list to the driver
+  struct sde_drm_wb_cfg wb_cfg = {};
+  wb_cfg.connector_id = token_.conn_id;
+  wb_cfg.flags = SDE_DRM_WB_CFG_FLAGS_CONNECTED;
+  wb_cfg.count_modes = UINT32(connector_info_.modes.size());
+  wb_cfg.modes = (uint64_t)connector_info_.modes.data();
+#ifdef DRM_IOCTL_SDE_WB_CONFIG
+  ret = drmIoctl(dev_fd_, DRM_IOCTL_SDE_WB_CONFIG, &wb_cfg);
+#endif
+  if (ret) {
+    DLOGE("Dump WBConfig: mode_count %d flags %x", wb_cfg.count_modes, wb_cfg.flags);
+    DumpConnectorModeInfo();
+    return kErrorHardware;
+  }
+  // Reload connector info for updated info after null commit
+  drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
+  InitializeConfigs();
+
+  GetModeIndex(display_attributes, &mode_index);
+  if (mode_index < 0) {
+    DLOGE("Mode not found for resolution %dx%d fps %d", display_attributes.x_pixels,
+          display_attributes.y_pixels, UINT32(display_attributes.fps));
+    DumpConnectorModeInfo();
+    return kErrorNotSupported;
+  }
+  current_mode_index_ = UINT32(mode_index);
+
+  DumpConnectorModeInfo();
+
+  return kErrorNone;
+}
+
+void HWVirtualDRM::DumpConnectorModeInfo() {
   for (uint32_t i = 0; i < (uint32_t)connector_info_.modes.size(); i++) {
-  DLOGI(
-    "Name: %s\tvref: %d\thdisp: %d\t hsync_s: %d\thsync_e:%d\thtotal: %d\t"
-    "vdisp: %d\tvsync_s: %d\tvsync_e: %d\tvtotal: %d\n",
-    connector_info_.modes[i].name, connector_info_.modes[i].vrefresh,
-    connector_info_.modes[i].hdisplay,
-    connector_info_.modes[i].hsync_start, connector_info_.modes[i].hsync_end,
-    connector_info_.modes[i].htotal, connector_info_.modes[i].vdisplay,
-    connector_info_.modes[i].vsync_start, connector_info_.modes[i].vsync_end,
-    connector_info_.modes[i].vtotal);
+    DLOGI("Mode[%d]: Name: %s\tvref: %d\thdisp: %d\t hsync_s: %d\thsync_e:%d\thtotal: %d\t" \
+          "vdisp: %d\tvsync_s: %d\tvsync_e: %d\tvtotal: %d\n", i, connector_info_.modes[i].name,
+          connector_info_.modes[i].vrefresh, connector_info_.modes[i].hdisplay,
+          connector_info_.modes[i].hsync_start, connector_info_.modes[i].hsync_end,
+          connector_info_.modes[i].htotal, connector_info_.modes[i].vdisplay,
+          connector_info_.modes[i].vsync_start, connector_info_.modes[i].vsync_end,
+          connector_info_.modes[i].vtotal);
   }
 }
 
@@ -144,6 +165,12 @@
   LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
   DisplayError err = kErrorNone;
 
+  if (first_cycle_) {
+    drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, token_.conn_id, token_.crtc_id);
+    drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::ON);
+    first_cycle_ = false;
+  }
+
   registry_.RegisterCurrent(hw_layers);
   registry_.MapBufferToFbId(output_buffer);
   uint32_t fb_id = registry_.GetFbId(output_buffer->planes[0].fd);
@@ -153,13 +180,30 @@
   ConfigureWbConnectorSecureMode(output_buffer->flags.secure);
 
   err = HWDeviceDRM::AtomicCommit(hw_layers);
+  if (err != kErrorNone) {
+    DLOGE("Atomic commit failed for crtc_id %d conn_id %d", token_.crtc_id, token_.conn_id);
+  }
   registry_.UnregisterNext();
+
   return(err);
 }
 
 DisplayError HWVirtualDRM::Validate(HWLayers *hw_layers) {
-  // TODO(user) : Add validate support
-  return kErrorNone;
+  LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+
+  if (first_cycle_) {
+    drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, token_.conn_id, token_.crtc_id);
+    drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::ON);
+  }
+
+  registry_.MapBufferToFbId(output_buffer);
+  uint32_t fb_id = registry_.GetFbId(output_buffer->planes[0].fd);
+
+  ConfigureWbConnectorFbId(fb_id);
+  ConfigureWbConnectorDestRect();
+  ConfigureWbConnectorSecureMode(output_buffer->flags.secure);
+
+  return HWDeviceDRM::Validate(hw_layers);
 }
 
 DisplayError HWVirtualDRM::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) {
@@ -167,55 +211,46 @@
     return kErrorParameters;
   }
 
-  uint32_t index = current_mode_index_;
-  width_ = display_attributes.x_pixels;
-  height_ = display_attributes.y_pixels;
-
-  DisplayError error = DeferredInit();
-  if (error != kErrorNone) {
-    width_ = display_attributes_[index].x_pixels;
-    height_ = display_attributes_[index].y_pixels;
-    return error;
+  int mode_index = -1;
+  GetModeIndex(display_attributes, &mode_index);
+  if (mode_index < 0) {
+    DisplayError error = SetWbConfigs(display_attributes);
+    if (error != kErrorNone) {
+      return error;
+    }
+  } else {
+    current_mode_index_ = UINT32(mode_index);
   }
-
-  display_attributes_[index] = display_attributes;
-  if (display_attributes_[index].x_pixels > hw_resource_.max_mixer_width) {
-    display_attributes_[index].is_device_split = true;
-  }
+  PopulateHWPanelInfo();
   UpdateMixerAttributes();
 
+  DLOGI("New WB Resolution: %dx%d cur_mode_index %d", display_attributes.x_pixels,
+        display_attributes.y_pixels, current_mode_index_);
   return kErrorNone;
 }
 
 DisplayError HWVirtualDRM::PowerOn() {
-  drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
-  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::ON);
-  return kErrorNone;
-}
+  if (first_cycle_) {
+    return kErrorNone;
+  }
 
-DisplayError HWVirtualDRM::PowerOff() {
-  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::OFF);
-  drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 0);
-  return kErrorNone;
+  return HWDeviceDRM::PowerOn();
 }
 
 DisplayError HWVirtualDRM::GetPPFeaturesVersion(PPFeatureVersion *vers) {
   return kErrorNone;
 }
 
-DisplayError HWVirtualDRM::SetScaleLutConfig(HWScaleLutInfo *lut_info) {
-  drm_lut_info_.cir_lut = lut_info->cir_lut;
-  drm_lut_info_.dir_lut = lut_info->dir_lut;
-  drm_lut_info_.sep_lut = lut_info->sep_lut;
-  drm_lut_info_.cir_lut_size = lut_info->cir_lut_size;
-  drm_lut_info_.dir_lut_size = lut_info->dir_lut_size;
-  drm_lut_info_.sep_lut_size = lut_info->sep_lut_size;
-
-  // Due to differed Init in WB case, we cannot set scaler config immediately as we
-  // won't have SDE DRM initialized at this point. Hence have to cache LUT info here
-  // and set it in ::DeferredInit
-
-  return kErrorNone;
+void HWVirtualDRM::GetModeIndex(const HWDisplayAttributes &display_attributes, int *mode_index) {
+  *mode_index = -1;
+  for (uint32_t i = 0; i < connector_info_.modes.size(); i++) {
+    if (display_attributes.x_pixels == connector_info_.modes[i].hdisplay &&
+        display_attributes.y_pixels == connector_info_.modes[i].vdisplay &&
+        display_attributes.fps == connector_info_.modes[i].vrefresh) {
+      *mode_index = INT32(i);
+      break;
+    }
+  }
 }
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_virtual_drm.h b/sdm/libs/core/drm/hw_virtual_drm.h
index 7fa6c54..53e5b56 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.h
+++ b/sdm/libs/core/drm/hw_virtual_drm.h
@@ -33,6 +33,7 @@
 #include "hw_device_drm.h"
 #include <drm/msm_drm.h>
 #include <drm/sde_drm.h>
+#include <vector>
 
 namespace sdm {
 
@@ -46,26 +47,22 @@
     return kErrorNotSupported;
   }
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
+  virtual DisplayError PowerOn();
 
  protected:
   virtual DisplayError Init();
   virtual DisplayError Validate(HWLayers *hw_layers);
-  virtual DisplayError DeferredInit();
-  virtual void InitializeConfigs();
   virtual DisplayError Commit(HWLayers *hw_layers);
   virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
-  virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
-  virtual DisplayError PowerOn();
-  virtual DisplayError PowerOff();
+
+ private:
   void ConfigureWbConnectorFbId(uint32_t fb_id);
   void ConfigureWbConnectorDestRect();
   void ConfigureWbConnectorSecureMode(bool secure);
-  void DumpConfigs();
-
- private:
-  uint32_t width_ = 0;
-  uint32_t height_ = 0;
-  sde_drm::DRMScalerLUTInfo drm_lut_info_ = {};
+  void InitializeConfigs();
+  void DumpConnectorModeInfo();
+  DisplayError SetWbConfigs(const HWDisplayAttributes &display_attributes);
+  void GetModeIndex(const HWDisplayAttributes &display_attributes, int *mode_index);
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/hw_interface.cpp b/sdm/libs/core/hw_interface.cpp
index 2d8d41e..902dcbc 100644
--- a/sdm/libs/core/hw_interface.cpp
+++ b/sdm/libs/core/hw_interface.cpp
@@ -35,7 +35,7 @@
 #include "fb/hw_primary.h"
 #include "fb/hw_hdmi.h"
 #include "fb/hw_virtual.h"
-#include "drm/hw_device_drm.h"
+#include "drm/hw_peripheral_drm.h"
 #include "drm/hw_virtual_drm.h"
 #include "drm/hw_tv_drm.h"
 
@@ -55,7 +55,7 @@
       if (driver_type == DriverType::FB) {
         hw = new HWPrimary(buffer_sync_handler, hw_info_intf);
       } else {
-        hw = new HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf);
+        hw = new HWPeripheralDRM(buffer_sync_handler, buffer_allocator, hw_info_intf);
       }
       break;
     case kHDMI:
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 0530db8..03e37aa 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -884,6 +884,8 @@
     return HWC2::Error::BadParameter;
   }
 
+  Layer *sdm_layer = client_target_->GetSDMLayer();
+  sdm_layer->frame_rate = current_refresh_rate_;
   client_target_->SetLayerBuffer(target, acquire_fence);
   client_target_->SetLayerSurfaceDamage(damage);
   if (client_target_->GetLayerDataspace() != dataspace) {
@@ -909,7 +911,7 @@
   return kErrorNotSupported;
 }
 
-void HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+HWC2::Error HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
   dump_frame_count_ = count;
   dump_frame_index_ = 0;
   dump_input_layers_ = ((bit_mask_layer_type & (1 << INPUT_LAYER_DUMP)) != 0);
@@ -920,6 +922,7 @@
 
   DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
   validated_ = false;
+  return HWC2::Error::None;
 }
 
 HWC2::PowerMode HWCDisplay::GetLastPowerMode() {
@@ -1435,6 +1438,7 @@
     return;
   }
 
+  DLOGI("dump_frame_count %d dump_input_layers %d", dump_frame_count_, dump_input_layers_);
   snprintf(dir_path, sizeof(dir_path), "%s/frame_dump_%s", HWCDebugHandler::DumpDir(),
            GetDisplayString());
 
@@ -1456,13 +1460,16 @@
     auto acquire_fence_fd = layer->input_buffer.acquire_fence_fd;
 
     if (acquire_fence_fd >= 0) {
-      int error = sync_wait(acquire_fence_fd, 1000);
-      if (error < 0) {
-        DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
-        return;
+      DisplayError error = buffer_allocator_->MapBuffer(pvt_handle, acquire_fence_fd);
+      if (error != kErrorNone) {
+        continue;
       }
     }
 
+
+    DLOGI("Dump layer[%d] of %d pvt_handle %x pvt_handle->base %x", i, layer_stack_.layers.size(),
+          pvt_handle, pvt_handle? pvt_handle->base : 0);
+
     if (pvt_handle && pvt_handle->base) {
       char dump_file_name[PATH_MAX];
       size_t result = 0;
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 654cba5..b3257f9 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -107,7 +107,7 @@
 
   // Framebuffer configurations
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
-  virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+  virtual HWC2::Error SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) {
     return kErrorNotSupported;
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp
index fb94715..50f5aeb 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -483,13 +483,13 @@
   }
 }
 
-void HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+HWC2::Error HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
   HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
   dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
   DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
 
   if (!count || !dump_output_to_file_) {
-    return;
+    return HWC2::Error::None;
   }
 
   // Allocate and map output buffer
@@ -502,7 +502,7 @@
   if (buffer_allocator_->AllocateBuffer(&output_buffer_info_) != 0) {
     DLOGE("Buffer allocation failed");
     output_buffer_info_ = {};
-    return;
+    return HWC2::Error::NoResources;
   }
 
   void *buffer = mmap(NULL, output_buffer_info_.alloc_buffer_info.size, PROT_READ | PROT_WRITE,
@@ -512,13 +512,14 @@
     DLOGE("mmap failed with err %d", errno);
     buffer_allocator_->FreeBuffer(&output_buffer_info_);
     output_buffer_info_ = {};
-    return;
+    return HWC2::Error::NoResources;
   }
 
   output_buffer_base_ = buffer;
   post_processed_output_ = true;
   DisablePartialUpdateOneFrame();
   validated_ = false;
+  return HWC2::Error::None;
 }
 
 int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo &output_buffer_info,
diff --git a/sdm/libs/hwc2/hwc_display_primary.h b/sdm/libs/hwc2/hwc_display_primary.h
index 49840c5..daf832d 100644
--- a/sdm/libs/hwc2/hwc_display_primary.h
+++ b/sdm/libs/hwc2/hwc_display_primary.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -63,7 +63,7 @@
   virtual void SetSecureDisplay(bool secure_display_active);
   virtual DisplayError Refresh();
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
-  virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+  virtual HWC2::Error SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
   virtual int FrameCaptureAsync(const BufferInfo &output_buffer_info, bool post_processed);
   virtual int GetFrameCaptureStatus() { return frame_capture_status_; }
   virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data);
diff --git a/sdm/libs/hwc2/hwc_display_virtual.cpp b/sdm/libs/hwc2/hwc_display_virtual.cpp
index 7505b01..719167a 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -179,7 +179,11 @@
   variable_info.y_pixels = height;
   // TODO(user): Need to get the framerate of primary display and update it.
   variable_info.fps = 60;
-  return display_intf_->SetActiveConfig(&variable_info);
+  DisplayError err = display_intf_->SetActiveConfig(&variable_info);
+  if (err != kErrorNone) {
+    return -EINVAL;
+  }
+  return 0;
 }
 
 HWC2::Error HWCDisplayVirtual::SetOutputBuffer(buffer_handle_t buf, int32_t release_fence) {
@@ -192,38 +196,53 @@
   output_buffer_->acquire_fence_fd = dup(release_fence);
 
   if (output_handle) {
-    output_handle_ = output_handle;
-    output_buffer_->buffer_id = reinterpret_cast<uint64_t>(output_handle);
     int output_handle_format = output_handle->format;
+    int active_aligned_w, active_aligned_h;
+    int new_width, new_height;
+    int new_aligned_w, new_aligned_h;
+    uint32_t active_width, active_height;
+    ColorMetaData color_metadata = {};
 
     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) {
+    LayerBufferFormat new_sdm_format = GetSDMFormat(output_handle_format, output_handle->flags);
+    if (new_sdm_format == kFormatInvalid) {
       return HWC2::Error::BadParameter;
     }
 
-    int aligned_width, aligned_height;
-#ifdef USE_GRALLOC1
-    buffer_allocator_->GetCustomWidthAndHeight(output_handle, &aligned_width, &aligned_height);
-#else
-    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, aligned_width,
-                                                          aligned_height);
-#endif
+    if (sdm::SetCSC(output_handle, &color_metadata) != kErrorNone) {
+      return HWC2::Error::BadParameter;
+    }
 
-    output_buffer_->width = UINT32(aligned_width);
-    output_buffer_->height = UINT32(aligned_height);
-    output_buffer_->unaligned_width = UINT32(output_handle->unaligned_width);
-    output_buffer_->unaligned_height = UINT32(output_handle->unaligned_height);
+    GetMixerResolution(&active_width, &active_height);
+    buffer_allocator_->GetCustomWidthAndHeight(output_handle, &new_width, &new_height);
+    buffer_allocator_->GetAlignedWidthAndHeight(INT(new_width), INT(new_height),
+                                                output_handle_format, 0, &new_aligned_w,
+                                                &new_aligned_h);
+    buffer_allocator_->GetAlignedWidthAndHeight(INT(active_width), INT(active_height),
+                                                output_handle_format, 0, &active_aligned_w,
+                                                &active_aligned_h);
+    if (new_aligned_w != active_aligned_w  || new_aligned_h != active_aligned_h) {
+      int status = SetConfig(UINT32(new_width), UINT32(new_height));
+      if (status) {
+        DLOGE("SetConfig failed custom WxH %dx%d", new_width, new_height);
+        return HWC2::Error::BadParameter;
+      }
+      validated_ = false;
+    }
+
+    output_buffer_->width = UINT32(new_aligned_w);
+    output_buffer_->height = UINT32(new_aligned_h);
+    output_buffer_->unaligned_width = UINT32(new_width);
+    output_buffer_->unaligned_height = UINT32(new_height);
     output_buffer_->flags.secure = 0;
     output_buffer_->flags.video = 0;
-
-    if (sdm::SetCSC(output_handle, &output_buffer_->color_metadata) != kErrorNone) {
-      return HWC2::Error::BadParameter;
-    }
+    output_buffer_->buffer_id = reinterpret_cast<uint64_t>(output_handle);
+    output_buffer_->format = new_sdm_format;
+    output_buffer_->color_metadata = color_metadata;
+    output_handle_ = output_handle;
 
     // TZ Protected Buffer - L1
     if (output_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
@@ -239,11 +258,12 @@
   return HWC2::Error::None;
 }
 
-void HWCDisplayVirtual::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+HWC2::Error HWCDisplayVirtual::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
   HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
   dump_output_layer_ = ((bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP)) != 0);
 
   DLOGI("output_layer_dump_enable %d", dump_output_layer_);
+  return HWC2::Error::None;
 }
 
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display_virtual.h b/sdm/libs/hwc2/hwc_display_virtual.h
index 36e8509..cf630fb 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.h
+++ b/sdm/libs/hwc2/hwc_display_virtual.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -46,7 +46,7 @@
   virtual int Deinit();
   virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
   virtual HWC2::Error Present(int32_t *out_retire_fence);
-  virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+  virtual HWC2::Error SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
   HWC2::Error SetOutputBuffer(buffer_handle_t buf, int32_t release_fence);
 
  private:
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 6a33b8f..2466413 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -548,6 +548,12 @@
       case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
         format = kFormatYCbCr420SPVenusUbwc;
         break;
+      case HAL_PIXEL_FORMAT_RGBA_1010102:
+        format = kFormatRGBA1010102Ubwc;
+        break;
+      case HAL_PIXEL_FORMAT_RGBX_1010102:
+        format = kFormatRGBX1010102Ubwc;
+        break;
       case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
         format = kFormatYCbCr420TP10Ubwc;
         break;
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 99fbc1a..31e61f0 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -944,34 +944,59 @@
 // Qclient methods
 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
                                              android::Parcel *output_parcel) {
-  android::status_t status = 0;
+  android::status_t status = -EINVAL;
 
   switch (command) {
     case qService::IQService::DYNAMIC_DEBUG:
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
+      status = 0;
       DynamicDebug(input_parcel);
       break;
 
     case qService::IQService::SCREEN_REFRESH:
-      refreshScreen();
+      status = refreshScreen();
       break;
 
     case qService::IQService::SET_IDLE_TIMEOUT:
-      setIdleTimeout(UINT32(input_parcel->readInt32()));
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
+      status = setIdleTimeout(UINT32(input_parcel->readInt32()));
       break;
 
     case qService::IQService::SET_FRAME_DUMP_CONFIG:
-      SetFrameDumpConfig(input_parcel);
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
+      status = SetFrameDumpConfig(input_parcel);
       break;
 
     case qService::IQService::SET_MAX_PIPES_PER_MIXER:
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
       status = SetMaxMixerStages(input_parcel);
       break;
 
     case qService::IQService::SET_DISPLAY_MODE:
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
       status = SetDisplayMode(input_parcel);
       break;
 
     case qService::IQService::SET_SECONDARY_DISPLAY_STATUS: {
+        if (!input_parcel || !output_parcel) {
+          DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
+          break;
+        }
         int disp_id = INT(input_parcel->readInt32());
         HWCDisplay::DisplayStatus disp_status =
               static_cast<HWCDisplay::DisplayStatus>(input_parcel->readInt32());
@@ -981,13 +1006,22 @@
       break;
 
     case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
       status = ConfigureRefreshRate(input_parcel);
       break;
 
     case qService::IQService::SET_VIEW_FRAME:
+      status = 0;
       break;
 
     case qService::IQService::TOGGLE_SCREEN_UPDATES: {
+        if (!input_parcel || !output_parcel) {
+          DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
+          break;
+        }
         int32_t input = input_parcel->readInt32();
         status = toggleScreenUpdate(input == 1);
         output_parcel->writeInt32(status);
@@ -995,10 +1029,18 @@
       break;
 
     case qService::IQService::QDCM_SVC_CMDS:
+      if (!input_parcel || !output_parcel) {
+        DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
+        break;
+      }
       status = QdcmCMDHandler(input_parcel, output_parcel);
       break;
 
     case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED: {
+        if (!input_parcel || !output_parcel) {
+          DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
+          break;
+        }
         int disp_id = input_parcel->readInt32();
         uint32_t min_enc_level = UINT32(input_parcel->readInt32());
         status = MinHdcpEncryptionLevelChanged(disp_id, min_enc_level);
@@ -1007,6 +1049,10 @@
       break;
 
     case qService::IQService::CONTROL_PARTIAL_UPDATE: {
+        if (!input_parcel || !output_parcel) {
+          DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
+          break;
+        }
         int disp_id = input_parcel->readInt32();
         uint32_t enable = UINT32(input_parcel->readInt32());
         status = ControlPartialUpdate(disp_id, enable == 1);
@@ -1015,6 +1061,10 @@
       break;
 
     case qService::IQService::SET_ACTIVE_CONFIG: {
+        if (!input_parcel) {
+          DLOGE("QService command = %d: input_parcel needed.", command);
+          break;
+        }
         uint32_t config = UINT32(input_parcel->readInt32());
         int disp_id = input_parcel->readInt32();
         status = SetActiveConfigIndex(disp_id, config);
@@ -1022,6 +1072,10 @@
       break;
 
     case qService::IQService::GET_ACTIVE_CONFIG: {
+        if (!input_parcel || !output_parcel) {
+          DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
+          break;
+        }
         int disp_id = input_parcel->readInt32();
         uint32_t config = 0;
         status = GetActiveConfigIndex(disp_id, &config);
@@ -1030,6 +1084,10 @@
       break;
 
     case qService::IQService::GET_CONFIG_COUNT: {
+        if (!input_parcel || !output_parcel) {
+          DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
+          break;
+        }
         int disp_id = input_parcel->readInt32();
         uint32_t count = 0;
         status = GetConfigCount(disp_id, &count);
@@ -1038,10 +1096,18 @@
       break;
 
     case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
+      if (!input_parcel || !output_parcel) {
+        DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
+        break;
+      }
       status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
       break;
 
     case qService::IQService::GET_PANEL_BRIGHTNESS: {
+        if (!output_parcel) {
+          DLOGE("QService command = %d: output_parcel needed.", command);
+          break;
+        }
         int level = 0;
         status = GetPanelBrightness(&level);
         output_parcel->writeInt32(level);
@@ -1049,6 +1115,10 @@
       break;
 
     case qService::IQService::SET_PANEL_BRIGHTNESS: {
+        if (!input_parcel || !output_parcel) {
+          DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
+          break;
+        }
         uint32_t level = UINT32(input_parcel->readInt32());
         status = setPanelBrightness(level);
         output_parcel->writeInt32(status);
@@ -1056,16 +1126,28 @@
       break;
 
     case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
+      if (!input_parcel || !output_parcel) {
+        DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
+        break;
+      }
       status = GetVisibleDisplayRect(input_parcel, output_parcel);
       break;
 
     case qService::IQService::SET_CAMERA_STATUS: {
+        if (!input_parcel) {
+          DLOGE("QService command = %d: input_parcel needed.", command);
+          break;
+        }
         uint32_t camera_status = UINT32(input_parcel->readInt32());
         status = setCameraLaunchStatus(camera_status);
       }
       break;
 
     case qService::IQService::GET_BW_TRANSACTION_STATUS: {
+        if (!output_parcel) {
+          DLOGE("QService command = %d: output_parcel needed.", command);
+          break;
+        }
         bool state = true;
         status = DisplayBWTransactionPending(&state);
         output_parcel->writeInt32(state);
@@ -1073,24 +1155,41 @@
       break;
 
     case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
       status = SetMixerResolution(input_parcel);
       break;
 
     case qService::IQService::SET_COLOR_MODE:
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
       status = SetColorModeOverride(input_parcel);
       break;
 
     case qService::IQService::SET_COLOR_MODE_BY_ID:
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
       status = SetColorModeById(input_parcel);
       break;
 
     case qService::IQService::GET_COMPOSER_STATUS:
+      if (!output_parcel) {
+        DLOGE("QService command = %d: output_parcel needed.", command);
+        break;
+      }
+      status = 0;
       output_parcel->writeInt32(getComposerStatus());
       break;
 
     default:
-      DLOGW("QService command = %d is not supported", command);
-      return -EINVAL;
+      DLOGW("QService command = %d is not supported.", command);
+      break;
   }
 
   return status;
@@ -1134,6 +1233,11 @@
   uint32_t operation = UINT32(input_parcel->readInt32());
   HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
 
+  if (!hwc_display) {
+    DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
+    return -ENODEV;
+  }
+
   switch (operation) {
     case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
       return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
@@ -1157,6 +1261,11 @@
 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
 
+  if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
+    return -ENODEV;
+  }
+
   uint32_t mode = UINT32(input_parcel->readInt32());
   return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
 }
@@ -1165,65 +1274,56 @@
   DisplayError error = kErrorNone;
   std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
   uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
+  android::status_t status = 0;
 
-  if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
-    SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
-    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
-      error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
-      if (error != kErrorNone) {
-        return -EINVAL;
+  for (uint32_t disp_id = HWC_DISPLAY_PRIMARY; disp_id < HWC_NUM_DISPLAY_TYPES; disp_id++) {
+    if (bit_mask_display_type[disp_id]) {
+      SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+      if (hwc_display_[disp_id]) {
+        error = hwc_display_[disp_id]->SetMaxMixerStages(max_mixer_stages);
+        if (error != kErrorNone) {
+          status = -EINVAL;
+          continue;
+        }
+      } else {
+        DLOGW("Display = %d is not connected.", disp_id);
+        status = (status)? status : -ENODEV;  // Return higher priority error.
+        continue;
       }
     }
   }
 
-  if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
-    SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
-    if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
-      error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
-      if (error != kErrorNone) {
-        return -EINVAL;
-      }
-    }
-  }
-
-  if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
-    SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
-    if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
-      error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
-      if (error != kErrorNone) {
-        return -EINVAL;
-      }
-    }
-  }
-
-  return 0;
+  return status;
 }
 
-void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
+android::status_t HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
   uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
   std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
   uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
+  android::status_t status = 0;
 
-  if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
-    SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
-    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
-      hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+  for (uint32_t disp_id = HWC_DISPLAY_PRIMARY; disp_id < HWC_NUM_DISPLAY_TYPES; disp_id++) {
+    if (bit_mask_display_type[disp_id]) {
+      SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+      if (hwc_display_[disp_id]) {
+        HWC2::Error error;
+        error = hwc_display_[disp_id]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+        if (HWC2::Error::None != error) {
+          if (HWC2::Error::NoResources == error)
+            status = -ENOMEM;
+          else
+            status = -EINVAL;
+          continue;
+        }
+      } else {
+        DLOGW("Display = %d is not connected.", disp_id);
+        status = (status)? status : -ENODEV;  // Return higher priority error.
+        continue;
+      }
     }
   }
 
-  if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
-    SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
-    if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
-      hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
-    }
-  }
-
-  if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
-    SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
-    if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
-      hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
-    }
-  }
+  return status;
 }
 
 android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
@@ -1231,14 +1331,14 @@
   uint32_t dpy = UINT32(input_parcel->readInt32());
 
   if (dpy != HWC_DISPLAY_PRIMARY) {
-    DLOGI("Resoulution change not supported for this display %d", dpy);
+    DLOGW("Resolution change not supported for this display = %d", dpy);
     return -EINVAL;
   }
 
   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
   if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
-    DLOGI("Primary display is not initialized");
-    return -EINVAL;
+    DLOGW("Primary display is not initialized");
+    return -ENODEV;
   }
 
   uint32_t width = UINT32(input_parcel->readInt32());
@@ -1285,8 +1385,6 @@
 }
 
 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
-  // TODO(user): Do we really need a lock here?
-
   int type = input_parcel->readInt32();
   bool enable = (input_parcel->readInt32() > 0);
   DLOGI("type = %d enable = %d", type, enable);
@@ -1338,7 +1436,8 @@
   PPDisplayAPIPayload resp_payload, req_payload;
 
   if (!color_mgr_) {
-    return -1;
+    DLOGW("color_mgr_ not initialized.");
+    return -ENOENT;
   }
 
   pending_action.action = kNoAction;
@@ -1347,13 +1446,21 @@
   // Read display_id, payload_size and payload from in_parcel.
   ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
   if (!ret) {
-    if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY])
-      ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload, &resp_payload,
-                                                                    &pending_action);
+    if ((display_id >= HWC_NUM_DISPLAY_TYPES) || !hwc_display_[display_id]) {
+      DLOGW("Invalid display id or display = %d is not connected.", display_id);
+      ret = -ENODEV;
+    }
+  }
 
-    if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL])
-      ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload,
-                                                                     &pending_action);
+  if (!ret) {
+    if ((HWC_DISPLAY_PRIMARY == display_id) || (HWC_DISPLAY_EXTERNAL == display_id)) {
+      ret = hwc_display_[display_id]->ColorSVCRequestRoute(req_payload, &resp_payload,
+                                                           &pending_action);
+    } else {
+      // Virtual, Tertiary etc. not supported.
+      DLOGW("Operation not supported on display = %d.", display_id);
+      ret = -EINVAL;
+    }
   }
 
   if (ret) {
@@ -1363,7 +1470,14 @@
     return ret;
   }
 
-  switch (pending_action.action) {
+  if (kNoAction != pending_action.action) {
+    // Restrict pending actions to primary display.
+    if (HWC_DISPLAY_PRIMARY != display_id) {
+      DLOGW("Skipping pending action %d on display = %d.", pending_action.action, display_id);
+      pending_action.action = kNoAction;
+    }
+
+    switch (pending_action.action) {
     case kInvalidating:
       Refresh(HWC_DISPLAY_PRIMARY);
       break;
@@ -1387,10 +1501,10 @@
       brightness_value = reinterpret_cast<int32_t *>(resp_payload.payload);
       if (brightness_value == NULL) {
         DLOGE("Brightness value is Null");
-        return -EINVAL;
-      }
-      if (HWC_DISPLAY_PRIMARY == display_id)
+        ret = -EINVAL;
+      } else {
         ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
+      }
       break;
     case kEnableFrameCapture:
       ret = color_mgr_->SetFrameCapture(pending_action.params, true,
@@ -1411,6 +1525,7 @@
     default:
       DLOGW("Invalid pending action = %d!", pending_action.action);
       break;
+    }
   }
 
   // for display API getter case, marshall returned params into out_parcel.
@@ -1420,7 +1535,7 @@
   resp_payload.DestroyPayload();
   hwc_display_[display_id]->ResetValidation();
 
-  return (ret ? -EINVAL : 0);
+  return ret;
 }
 
 void HWCSession::UEventHandler(const char *uevent_data, int length) {
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index df58093..fe69515 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -215,7 +215,7 @@
   virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
                                            android::Parcel *output_parcel);
   void DynamicDebug(const android::Parcel *input_parcel);
-  void SetFrameDumpConfig(const android::Parcel *input_parcel);
+  android::status_t SetFrameDumpConfig(const android::Parcel *input_parcel);
   android::status_t SetMaxMixerStages(const android::Parcel *input_parcel);
   android::status_t SetDisplayMode(const android::Parcel *input_parcel);
   android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 52eaf7a..64ac57c 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -386,7 +386,8 @@
     return 0;
   }
 
-  return -EINVAL;
+  DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
+  return -ENODEV;
 }
 
 Return<void> HWCSession::getHDRCapabilities(IDisplayConfig::DisplayType dpy,
@@ -394,9 +395,14 @@
   int32_t error = -EINVAL;
   IDisplayConfig::DisplayHDRCapabilities hdr_caps = {};
 
+  if (!_hidl_cb) {
+    DLOGE("_hidl_cb callback not provided.");
+    return Void();
+  }
+
   do {
     int disp_id = MapDisplayType(dpy);
-    if (disp_id < 0) {
+    if ((disp_id < 0) || (disp_id >= HWC_NUM_DISPLAY_TYPES)) {
       DLOGE("Invalid display id = %d", disp_id);
       break;
     }
@@ -404,7 +410,8 @@
     SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
     HWCDisplay *hwc_display = hwc_display_[disp_id];
     if (!hwc_display) {
-      DLOGE("Display = %d is not connected.", disp_id);
+      DLOGW("Display = %d is not connected.", disp_id);
+      error = -ENODEV;
       break;
     }
 
@@ -442,6 +449,16 @@
 Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
 
+  if (!core_intf_) {
+    DLOGW("core_intf_ not initialized.");
+    return -ENOENT;
+  }
+
+  if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
+    return -ENODEV;
+  }
+
   HWBwModes mode = on > 0 ? kBwCamera : kBwDefault;
 
   // trigger invalidate to apply new bw caps.
@@ -470,12 +487,18 @@
     return 0;
   }
 
-  return -EINVAL;
+  DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
+  return -ENODEV;
 }
 
 Return<void> HWCSession::displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) {
   bool status = true;
 
+  if (!_hidl_cb) {
+      DLOGE("_hidl_cb callback not provided.");
+      return Void();
+  }
+
   int32_t error = DisplayBWTransactionPending(&status);
 
   _hidl_cb(error, status);