Merge "sdm: Cleanup unused code, round 2"
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 8fddb43..35285ee 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -230,6 +230,12 @@
    */
   CRTC_SET_SECURITY_LEVEL,
   /*
+   * Op: sets solid fill stages
+   * Arg: uint32_t - CRTC ID
+   *      Vector of DRMSolidfillStage
+   */
+  CRTC_SET_SOLIDFILL_STAGES,
+  /*
    * Op: Returns retire fence for this commit. Should be called after Commit() on
    * DRMAtomicReqInterface.
    * Arg: uint32_t - Connector ID
@@ -321,6 +327,7 @@
 struct DRMCrtcInfo {
   bool has_src_split;
   uint32_t max_blend_stages;
+  uint32_t max_solidfill_stages;
   QSEEDVersion qseed_version;
   SmartDMARevision smart_dma_rev;
   float ib_fudge_factor;
@@ -471,6 +478,14 @@
   SECURE_ONLY,
 };
 
+struct DRMSolidfillStage {
+ DRMRect bounding_rect {};
+ bool is_exclusion_rect = false;
+ uint32_t color = 0xff000000; // in 8bit argb
+ uint32_t z_order = 0;
+ uint32_t plane_alpha = 0xff;
+};
+
 /* DRM Atomic Request Property Set.
  *
  * Helper class to create and populate atomic properties of DRM components
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 8cf1922..752d0c4 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -157,6 +157,7 @@
   uint32_t num_rgb_pipe = 0;
   uint32_t num_cursor_pipe = 0;
   uint32_t num_blending_stages = 0;
+  uint32_t num_solidfill_stages = 0;
   uint32_t num_control = 0;
   uint32_t num_mixer_to_disp = 0;
   uint32_t smp_total = 0;
@@ -460,11 +461,21 @@
   void Reset() { *this = HWPipeInfo(); }
 };
 
+struct HWSolidfillStage {
+  uint32_t z_order = kMaxSDELayers;
+  uint32_t color = 0;
+  LayerRect roi = {};
+  bool is_exclusion_rect = false;
+};
+
 struct HWLayerConfig {
   HWPipeInfo left_pipe;           // pipe for left side of output
   HWPipeInfo right_pipe;          // pipe for right side of output
   HWRotatorSession hw_rotator_session;
+  HWSolidfillStage hw_solidfill_stage;
+
   float compression = 1.0f;
+  bool use_solidfill_stage = false;
 
   void Reset() { *this = HWLayerConfig(); }
 };
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index f57d760..1e75298 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -48,7 +48,7 @@
                                           const HWPanelInfo &hw_panel_info,
                                           const HWMixerAttributes &mixer_attributes) = 0;
   virtual DisplayError Start(Handle display_ctx) = 0;
-  virtual DisplayError Stop(Handle display_ctx) = 0;
+  virtual DisplayError Stop(Handle display_ctx, HWLayers *hw_layers) = 0;
   virtual DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers) = 0;
   virtual DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers) = 0;
   virtual DisplayError Commit(Handle display_ctx, HWLayers *hw_layers) = 0;
diff --git a/sdm/include/utils/debug.h b/sdm/include/utils/debug.h
index 2bd6a5a..0b40e7b 100644
--- a/sdm/include/utils/debug.h
+++ b/sdm/include/utils/debug.h
@@ -63,7 +63,7 @@
   }
   static inline DebugHandler* Get() { return debug_.debug_handler_; }
   static int GetSimulationFlag();
-  static int GetHDMIResolution();
+  static bool GetExternalResolution(char *val);
   static void GetIdleTimeoutMs(uint32_t *active_ms, uint32_t *inactive_ms);
   static int GetBootAnimLayerCount();
   static bool IsRotatorDownScaleDisabled();
diff --git a/sdm/libs/core/Android.mk b/sdm/libs/core/Android.mk
index 991cfac..14df125 100644
--- a/sdm/libs/core/Android.mk
+++ b/sdm/libs/core/Android.mk
@@ -49,7 +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_hdmi_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 \
                                  $(LOCAL_HW_INTF_PATH_2)/hw_virtual_drm.cpp \
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index f35c1c6..4d25497 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -289,10 +289,12 @@
   }
 
   if (error != kErrorNone) {
+    resource_intf_->Stop(display_resource_ctx, hw_layers);
     DLOGE("Composition strategies exhausted for display = %d", display_comp_ctx->display_type);
+    return error;
   }
 
-  resource_intf_->Stop(display_resource_ctx);
+  error = resource_intf_->Stop(display_resource_ctx, hw_layers);
 
   return error;
 }
@@ -338,7 +340,7 @@
     DLOGE("Reconfigure failed for display = %d", display_comp_ctx->display_type);
   }
 
-  resource_intf_->Stop(display_resource_ctx);
+  resource_intf_->Stop(display_resource_ctx, hw_layers);
   if (error != kErrorNone) {
       error = resource_intf_->PostPrepare(display_resource_ctx, hw_layers);
   }
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
index a6c5c47..2ea2ac2 100644
--- a/sdm/libs/core/display_hdmi.cpp
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -185,37 +185,33 @@
       break;
     }
   }
-  if (index < num_modes) {
-    best_index = UINT32(index);
-    for (size_t index = best_index + 1; index < num_modes; index ++) {
-      if (!attrib[index].s3d_config[s3d_mode])
-        continue;
 
-      // From the available configs, select the best
-      // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60
+  index = 0;
+  best_index = UINT32(index);
+  for (size_t index = best_index + 1; index < num_modes; index ++) {
+    // TODO(user): Need to add support to S3D modes
+    // From the available configs, select the best
+    // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60
+    if (attrib[index].x_pixels > attrib[best_index].x_pixels) {
+      best_index = UINT32(index);
+    } else if (attrib[index].x_pixels == attrib[best_index].x_pixels) {
       if (attrib[index].y_pixels > attrib[best_index].y_pixels) {
         best_index = UINT32(index);
       } else if (attrib[index].y_pixels == attrib[best_index].y_pixels) {
-        if (attrib[index].x_pixels > attrib[best_index].x_pixels) {
+        if (attrib[index].vsync_period_ns < attrib[best_index].vsync_period_ns) {
           best_index = UINT32(index);
-        } else if (attrib[index].x_pixels == attrib[best_index].x_pixels) {
-          if (attrib[index].vsync_period_ns < attrib[best_index].vsync_period_ns) {
-            best_index = UINT32(index);
-          }
         }
       }
     }
-  } else {
-    DLOGW("%s, could not support S3D mode from EDID info. S3D mode is %d",
-          __FUNCTION__, s3d_mode);
   }
-
+  char val[kPropertyMax]={};
   // Used for changing HDMI Resolution - override the best with user set config
-  uint32_t user_config = UINT32(Debug::GetHDMIResolution());
+  bool user_config = (Debug::GetExternalResolution(val));
+
   if (user_config) {
     uint32_t config_index = 0;
     // For the config, get the corresponding index
-    DisplayError error = hw_intf_->GetConfigIndex(user_config, &config_index);
+    DisplayError error = hw_intf_->GetConfigIndex(val, &config_index);
     if (error == kErrorNone)
       return config_index;
   }
diff --git a/sdm/libs/core/display_hdmi.h b/sdm/libs/core/display_hdmi.h
index dfee684..8248840 100644
--- a/sdm/libs/core/display_hdmi.h
+++ b/sdm/libs/core/display_hdmi.h
@@ -61,6 +61,7 @@
   uint32_t GetBestConfig(HWS3DMode s3d_mode);
   void GetScanSupport();
   void SetS3DMode(LayerStack *layer_stack);
+  static const int kPropertyMax = 256;
 
   bool underscan_supported_ = false;
   HWScanSupport scan_support_;
diff --git a/sdm/libs/core/drm/hw_color_manager_drm.cpp b/sdm/libs/core/drm/hw_color_manager_drm.cpp
index 8c9eb24..67478c9 100644
--- a/sdm/libs/core/drm/hw_color_manager_drm.cpp
+++ b/sdm/libs/core/drm/hw_color_manager_drm.cpp
@@ -48,6 +48,9 @@
 #ifdef PP_DRM_ENABLE
 static const uint32_t kPgcDataMask = 0x3FF;
 static const uint32_t kPgcShift = 16;
+
+static const uint32_t kIgcDataMask = 0xFFF;
+static const uint32_t kIgcShift = 16;
 #endif
 
 namespace sdm {
@@ -76,6 +79,8 @@
     case kFeaturePcc:
       break;
     case kFeatureIgc:
+      if (feature.version == 3)
+        version = PPFeatureVersion::kSDEIgcV30;
       break;
     case kFeaturePgc:
       if (feature.version == 1)
@@ -144,6 +149,67 @@
 DisplayError HWColorManagerDrm::GetDrmIGC(const PPFeatureInfo &in_data,
                                           DRMPPFeatureInfo *out_data) {
   DisplayError ret = kErrorNone;
+#ifdef PP_DRM_ENABLE
+  struct SDEIgcV30LUTData *sde_igc;
+  struct drm_msm_igc_lut *mdp_igc;
+  uint32_t *c0_c1_data_ptr = NULL;
+  uint32_t *c2_data_ptr = NULL;
+
+
+  if (!out_data) {
+    DLOGE("Invalid input parameter for igc");
+    return kErrorParameters;
+  }
+
+  switch (in_data.feature_version_) {
+  case PPFeatureVersion::kSDEIgcV30:
+    sde_igc = (struct SDEIgcV30LUTData *) in_data.GetConfigData();
+    break;
+  default:
+    DLOGE("Unsupported igc feature version: %d", in_data.feature_version_);
+    return kErrorParameters;
+  }
+
+  out_data->id = kFeatureIgc;
+  out_data->type = sde_drm::kPropBlob;
+  out_data->version = in_data.feature_version_;
+  out_data->payload_size = sizeof(struct drm_msm_igc_lut);
+
+  if (in_data.enable_flags_ & kOpsDisable) {
+    /* feature disable case */
+    out_data->payload = NULL;
+    return ret;
+  } else if (!(in_data.enable_flags_ & kOpsEnable)) {
+    out_data->payload = NULL;
+    return kErrorParameters;
+  }
+
+  mdp_igc = new drm_msm_igc_lut();
+  if (!mdp_igc) {
+    DLOGE("Failed to allocate memory for igc");
+    return kErrorMemory;
+  }
+
+  mdp_igc->flags = IGC_DITHER_ENABLE;
+  mdp_igc->strength = sde_igc->strength;
+
+  c0_c1_data_ptr = reinterpret_cast<uint32_t*>(sde_igc->c0_c1_data);
+  c2_data_ptr = reinterpret_cast<uint32_t*>(sde_igc->c2_data);
+
+  if (!c0_c1_data_ptr || !c2_data_ptr) {
+    DLOGE("Invaid igc data pointer");
+    delete mdp_igc;
+    out_data->payload = NULL;
+    return kErrorParameters;
+  }
+
+  for (int i = 0; i < IGC_TBL_LEN; i++) {
+    mdp_igc->c0[i] = c0_c1_data_ptr[i] & kIgcDataMask;
+    mdp_igc->c1[i] = (c0_c1_data_ptr[i] >> kIgcShift) & kIgcDataMask;
+    mdp_igc->c2[i] = c2_data_ptr[i] & kIgcDataMask;
+  }
+  out_data->payload = mdp_igc;
+#endif
   return ret;
 }
 
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 29ac44e..9736ad0 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -606,7 +606,7 @@
   return kErrorNotSupported;
 }
 
-DisplayError HWDeviceDRM::GetConfigIndex(uint32_t mode, uint32_t *index) {
+DisplayError HWDeviceDRM::GetConfigIndex(char *mode, uint32_t *index) {
   return kErrorNone;
 }
 
@@ -668,6 +668,8 @@
   HWQosData &qos_data = hw_layers->qos_data;
   DRMSecurityLevel crtc_security_level = DRMSecurityLevel::SECURE_NON_SECURE;
 
+  solid_fills_.clear();
+
   // TODO(user): Once destination scalar is enabled we can always send ROIs if driver allows
   if (hw_panel_info_.partial_update) {
     const int kNumMaxROIs = 4;
@@ -703,6 +705,11 @@
     HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
     HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
 
+    if (hw_layers->config[i].use_solidfill_stage) {
+      AddSolidfillStage(hw_layers->config[i].hw_solidfill_stage, layer.plane_alpha);
+      continue;
+    }
+
     for (uint32_t count = 0; count < 2; count++) {
       HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
       HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
@@ -769,6 +776,7 @@
     }
   }
 
+  SetSolidfillStages();
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_CLK, token_.crtc_id, qos_data.clock_hz);
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_AB, token_.crtc_id, qos_data.core_ab_bps);
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_IB, token_.crtc_id, qos_data.core_ib_bps);
@@ -785,6 +793,28 @@
            qos_data.rot_clock_hz);
 }
 
+void HWDeviceDRM::AddSolidfillStage(const HWSolidfillStage &sf, uint32_t plane_alpha) {
+  sde_drm::DRMSolidfillStage solidfill;
+  solidfill.bounding_rect.left = UINT32(sf.roi.left);
+  solidfill.bounding_rect.top = UINT32(sf.roi.top);
+  solidfill.bounding_rect.right = UINT32(sf.roi.right);
+  solidfill.bounding_rect.bottom = UINT32(sf.roi.bottom);
+  solidfill.is_exclusion_rect  = sf.is_exclusion_rect;
+  solidfill.plane_alpha = plane_alpha;
+  solidfill.z_order = sf.z_order;
+  solidfill.color = sf.color;
+  solid_fills_.push_back(solidfill);
+  DLOGI_IF(kTagDriverConfig, "Add a solidfill stage at z_order:%d argb_color:%x plane_alpha:%x",
+           solidfill.z_order, solidfill.color, solidfill.plane_alpha);
+}
+
+void HWDeviceDRM::SetSolidfillStages() {
+  if (hw_resource_.num_solidfill_stages) {
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_SOLIDFILL_STAGES, token_.crtc_id,
+                              reinterpret_cast<uint64_t> (&solid_fills_));
+  }
+}
+
 DisplayError HWDeviceDRM::Validate(HWLayers *hw_layers) {
   DTRACE_SCOPED();
 
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index e754cfa..965ff3b 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -65,7 +65,7 @@
   virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
-  virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+  virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
   virtual DisplayError PowerOn();
   virtual DisplayError PowerOff();
   virtual DisplayError Doze();
@@ -118,6 +118,8 @@
   void ResetDisplayParams();
   bool EnableHotPlugDetection(int enable);
   void UpdateMixerAttributes();
+  void SetSolidfillStages();
+  void AddSolidfillStage(const HWSolidfillStage &sf, uint32_t plane_alpha);
   void SetBlending(const LayerBlending &source, sde_drm::DRMBlendType *target);
   void SetSrcConfig(const LayerBuffer &input_buffer, uint32_t *config);
   void SetRect(const LayerRect &source, sde_drm::DRMRect *target);
@@ -165,6 +167,7 @@
   HWResourceInfo hw_resource_ = {};
   HWPanelInfo hw_panel_info_ = {};
   HWDeviceType device_type_ = {};
+  HWScaleDRM *hw_scale_ = {};
   sde_drm::DRMManagerInterface *drm_mgr_intf_ = {};
   sde_drm::DRMAtomicReqInterface *drm_atomic_intf_ = {};
   sde_drm::DRMConnectorInfo connector_info_ = {};
@@ -175,7 +178,7 @@
   bool synchronous_commit_ = false;
   HWMixerAttributes mixer_attributes_ = {};
   std::string interface_str_ = "DSI";
-  HWScaleDRM *hw_scale_ = {};
+  std::vector<sde_drm::DRMSolidfillStage> solid_fills_ {};
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_hdmi_drm.cpp b/sdm/libs/core/drm/hw_hdmi_drm.cpp
deleted file mode 100644
index 27419c7..0000000
--- a/sdm/libs/core/drm/hw_hdmi_drm.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-*     * Redistributions of source code must retain the above copyright
-*       notice, this list of conditions and the following disclaimer.
-*     * Redistributions in binary form must reproduce the above
-*       copyright notice, this list of conditions and the following
-*       disclaimer in the documentation and/or other materials provided
-*       with the distribution.
-*     * Neither the name of The Linux Foundation nor the names of its
-*       contributors may be used to endorse or promote products derived
-*       from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <drm_lib_loader.h>
-#include <drm_master.h>
-#include <drm_res_mgr.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <utils/debug.h>
-#include <utils/sys.h>
-#include <utils/formats.h>
-
-#include <vector>
-#include <map>
-#include <utility>
-
-#include "hw_hdmi_drm.h"
-
-#define __CLASS__ "HWHDMIDRM"
-
-using drm_utils::DRMMaster;
-using drm_utils::DRMResMgr;
-using drm_utils::DRMLibLoader;
-using drm_utils::DRMBuffer;
-using sde_drm::GetDRMManager;
-using sde_drm::DestroyDRMManager;
-using sde_drm::DRMDisplayType;
-using sde_drm::DRMDisplayToken;
-using sde_drm::DRMConnectorInfo;
-using sde_drm::DRMPPFeatureInfo;
-using sde_drm::DRMOps;
-using sde_drm::DRMTopology;
-
-namespace sdm {
-
-HWHDMIDRM::HWHDMIDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
-                     HWInfoInterface *hw_info_intf)
-  : HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf),
-  active_config_index_(0) {
-  HWDeviceDRM::device_type_ = kDeviceHDMI;
-  HWDeviceDRM::device_name_ = "HDMI Display Device";
-}
-
-// TODO(user) : split function in base class and avoid code duplicacy
-// by using base implementation for this basic stuff
-DisplayError HWHDMIDRM::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();
-    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, &current_mode_);
-    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
-
-    if (drm_atomic_intf_->Commit(true /* synchronous */)) {
-      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_);
-    DLOGI("Setup CRTC %d, Connector %d for %s", token_.crtc_id, token_.conn_id, device_name_);
-  }
-
-  PopulateDisplayAttributes();
-  PopulateHWPanelInfo();
-  UpdateMixerAttributes();
-
-  return error;
-}
-
-DisplayError HWHDMIDRM::GetNumDisplayAttributes(uint32_t *count) {
-  *count = connector_info_.num_modes;
-  if (*count <= 0) {
-    return kErrorHardware;
-  }
-
-  return kErrorNone;
-}
-
-DisplayError HWHDMIDRM::GetActiveConfig(uint32_t *active_config_index) {
-  *active_config_index = active_config_index_;
-  return kErrorNone;
-}
-
-DisplayError HWHDMIDRM::SetDisplayAttributes(uint32_t index) {
-  DTRACE_SCOPED();
-
-  if (index >= connector_info_.num_modes) {
-    return kErrorNotSupported;
-  }
-
-  active_config_index_ = index;
-
-  // TODO(user): fix this hard coding
-  frame_rate_ = 60;
-
-  // Get the display attributes for current active config index
-  GetDisplayAttributes(active_config_index_, &display_attributes_);
-  UpdateMixerAttributes();
-
-  return kErrorNone;
-}
-
-DisplayError HWHDMIDRM::GetConfigIndex(uint32_t mode, uint32_t *index) {
-  *index = mode;
-
-  return kErrorNone;
-}
-
-DisplayError HWHDMIDRM::Validate(HWLayers *hw_layers) {
-  HWDeviceDRM::ResetDisplayParams();
-
-  return HWDeviceDRM::Validate(hw_layers);
-}
-
-DisplayError HWHDMIDRM::Commit(HWLayers *hw_layers) {
-  return HWDeviceDRM::Commit(hw_layers);
-}
-
-}  // namespace sdm
-
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index 7b632e8..69af1bd 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -254,6 +254,7 @@
   hw_resource->is_src_split = info.has_src_split;
   hw_resource->has_qseed3 = (info.qseed_version == sde_drm::QSEEDVersion::V3);
   hw_resource->num_blending_stages = info.max_blend_stages;
+  hw_resource->num_solidfill_stages = info.max_solidfill_stages;
   hw_resource->smart_dma_rev = (info.smart_dma_rev == sde_drm::SmartDMARevision::V2) ?
     SmartDMARevision::V2 : SmartDMARevision::V1;
   hw_resource->ib_fudge_factor = info.ib_fudge_factor;
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
new file mode 100644
index 0000000..0262915
--- /dev/null
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -0,0 +1,183 @@
+/*
+* 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 "hw_tv_drm.h"
+#include <utils/debug.h>
+#include <utils/sys.h>
+#include <utils/formats.h>
+#include <drm_lib_loader.h>
+#include <drm_master.h>
+#include <drm_res_mgr.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string>
+#include <vector>
+#include <map>
+#include <utility>
+
+
+#define __CLASS__ "HWTVDRM"
+
+using drm_utils::DRMMaster;
+using drm_utils::DRMResMgr;
+using drm_utils::DRMLibLoader;
+using drm_utils::DRMBuffer;
+using sde_drm::GetDRMManager;
+using sde_drm::DestroyDRMManager;
+using sde_drm::DRMDisplayType;
+using sde_drm::DRMDisplayToken;
+using sde_drm::DRMConnectorInfo;
+using sde_drm::DRMPPFeatureInfo;
+using sde_drm::DRMOps;
+using sde_drm::DRMTopology;
+
+namespace sdm {
+
+HWTVDRM::HWTVDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+                     HWInfoInterface *hw_info_intf)
+  : HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf), active_config_index_(0) {
+  disp_type_ = DRMDisplayType::TV;
+  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();
+  }
+
+  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);
+  }
+
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return error;
+}
+
+DisplayError HWTVDRM::GetNumDisplayAttributes(uint32_t *count) {
+  *count = connector_info_.num_modes;
+  if (*count <= 0) {
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWTVDRM::GetActiveConfig(uint32_t *active_config_index) {
+  *active_config_index = active_config_index_;
+  return kErrorNone;
+}
+
+DisplayError HWTVDRM::SetDisplayAttributes(uint32_t index) {
+  if (index >= connector_info_.num_modes) {
+    return kErrorNotSupported;
+  }
+
+  active_config_index_ = index;
+  current_mode_ = connector_info_.modes[index];
+
+  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);
+
+  // Commit to setup pipeline with mode, which then tells us the topology etc
+  if (drm_atomic_intf_->Commit(true /* synchronous */)) {
+    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_);
+  DLOGI("Setup CRTC %d, Connector %d for %s", token_.crtc_id, token_.conn_id, device_name_);
+
+  frame_rate_ = display_attributes_.fps;
+  PopulateDisplayAttributes();
+  PopulateHWPanelInfo();
+  UpdateMixerAttributes();
+
+  return kErrorNone;
+}
+
+DisplayError HWTVDRM::GetConfigIndex(char *mode, uint32_t *index) {
+  uint32_t width = 0, height = 0, fps = 0, format = 0;
+  std::string str(mode);
+
+  // mode should be in width:height:fps:format
+  // TODO(user): it is not fully robust, User needs to provide in above format only
+  if (str.length() != 0) {
+    width = UINT32(stoi(str));
+    height = UINT32(stoi(str.substr(str.find(':') + 1)));
+    std::string str3 = str.substr(str.find(':') + 1);
+    fps = UINT32(stoi(str3.substr(str3.find(':')  + 1)));
+    std::string str4 = str3.substr(str3.find(':') + 1);
+    format = UINT32(stoi(str4.substr(str4.find(':') + 1)));
+  }
+
+  for (size_t idex = 0; idex < connector_info_.num_modes; idex ++) {
+    if ((height == connector_info_.modes[idex].vdisplay) &&
+        (width == connector_info_.modes[idex].hdisplay) &&
+        (fps == connector_info_.modes[idex].vrefresh)) {
+      if ((format >> 1) & (connector_info_.modes[idex].flags >> kBitYUV)) {
+        *index = UINT32(idex);
+      }
+
+      if (format & (connector_info_.modes[idex].flags >> kBitRGB)) {
+        *index = UINT32(idex);
+      }
+    }
+  }
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/drm/hw_hdmi_drm.h b/sdm/libs/core/drm/hw_tv_drm.h
similarity index 84%
rename from sdm/libs/core/drm/hw_hdmi_drm.h
rename to sdm/libs/core/drm/hw_tv_drm.h
index 7e11e5e..7991ae3 100644
--- a/sdm/libs/core/drm/hw_hdmi_drm.h
+++ b/sdm/libs/core/drm/hw_tv_drm.h
@@ -22,8 +22,8 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#ifndef __HW_HDMI_DRM_H__
-#define __HW_HDMI_DRM_H__
+#ifndef __HW_TV_DRM_H__
+#define __HW_TV_DRM_H__
 
 #include <map>
 #include <vector>
@@ -34,9 +34,9 @@
 
 using std::vector;
 
-class HWHDMIDRM : public HWDeviceDRM {
+class HWTVDRM : public HWDeviceDRM {
  public:
-  explicit HWHDMIDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+  explicit HWTVDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
                      HWInfoInterface *hw_info_intf);
 
  protected:
@@ -45,16 +45,17 @@
   // Requirement to call this only after the first config has been explicitly set by client
   virtual DisplayError GetActiveConfig(uint32_t *active_config);
   virtual DisplayError SetDisplayAttributes(uint32_t index);
-  virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
-  virtual DisplayError Validate(HWLayers *hw_layers);
-  virtual DisplayError Commit(HWLayers *hw_layers);
+  virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
 
  private:
+  static const int kBitRGB  = 20;
+  static const int kBitYUV  = 21;
+
   uint32_t active_config_index_;
   uint32_t frame_rate_ = 0;
 };
 
 }  // namespace sdm
 
-#endif  // __HW_HDMI_DRM_H__
+#endif  // __HW_TV_DRM_H__
 
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index ff19753..4931e1b 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -146,7 +146,7 @@
   return kErrorNotSupported;
 }
 
-DisplayError HWDevice::GetConfigIndex(uint32_t mode, uint32_t *index) {
+DisplayError HWDevice::GetConfigIndex(char *mode, uint32_t *index) {
   return kErrorNone;
 }
 
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index 2c0593a..f32c5bd 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -69,7 +69,7 @@
   virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
-  virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+  virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
   virtual DisplayError PowerOn();
   virtual DisplayError PowerOff();
   virtual DisplayError Doze();
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index 334a043..0602b12 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -38,6 +38,7 @@
 #include <utils/sys.h>
 #include <utils/formats.h>
 
+#include <string>
 #include <vector>
 #include <map>
 #include <utility>
@@ -407,17 +408,20 @@
   return kErrorNone;
 }
 
-DisplayError HWHDMI::GetConfigIndex(uint32_t mode, uint32_t *index) {
+DisplayError HWHDMI::GetConfigIndex(char *mode, uint32_t *index) {
+  std::string str(mode);
+  uint32_t value = UINT32(stoi(str));
+
   // Check if the mode is valid and return corresponding index
   for (uint32_t i = 0; i < hdmi_modes_.size(); i++) {
-    if (hdmi_modes_[i] == mode) {
+    if (hdmi_modes_[i] == value) {
       *index = i;
-      DLOGI("Index = %d for config = %d", *index, mode);
+      DLOGI("Index = %d for config = %d", *index, value);
       return kErrorNone;
     }
   }
 
-  DLOGE("Config = %d not supported", mode);
+  DLOGE("Config = %d not supported", value);
   return kErrorNotSupported;
 }
 
@@ -864,7 +868,9 @@
     return kErrorNotSupported;
   }
 
-  GetConfigIndex(dst->video_format, config_index);
+  char mode_val[kVideoFormatArrayMax]={};
+  snprintf(mode_val, sizeof(mode_val), "%d", dst->video_format);
+  GetConfigIndex(mode_val, config_index);
 
   data->hor_front_porch = dst->front_porch_h;
   data->hor_back_porch = dst->back_porch_h;
diff --git a/sdm/libs/core/fb/hw_hdmi.h b/sdm/libs/core/fb/hw_hdmi.h
index 625782e..83025fa 100644
--- a/sdm/libs/core/fb/hw_hdmi.h
+++ b/sdm/libs/core/fb/hw_hdmi.h
@@ -83,7 +83,7 @@
   virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format);
   virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
   virtual DisplayError SetDisplayAttributes(uint32_t index);
-  virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+  virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
   virtual DisplayError Validate(HWLayers *hw_layers);
   virtual DisplayError Commit(HWLayers *hw_layers);
   virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
@@ -109,6 +109,7 @@
   DisplayError GetDynamicFrameRateMode(uint32_t refresh_rate, uint32_t*mode,
                                        DynamicFPSData *data, uint32_t *config_index);
   static const int kThresholdRefreshRate = 1000;
+  static const int kVideoFormatArrayMax = 8;
   vector<uint32_t> hdmi_modes_;
   // Holds the hdmi timing information. Ex: resolution, fps etc.,
   vector<msm_hdmi_mode_timing_info> supported_video_modes_;
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index 8102e5f..5ee8121 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -329,7 +329,7 @@
   return kErrorNone;
 }
 
-DisplayError HWPrimary::GetConfigIndex(uint32_t mode, uint32_t *index) {
+DisplayError HWPrimary::GetConfigIndex(char *mode, uint32_t *index) {
   return HWDevice::GetConfigIndex(mode, index);
 }
 
diff --git a/sdm/libs/core/fb/hw_primary.h b/sdm/libs/core/fb/hw_primary.h
index 38b3b9a..69b5445 100644
--- a/sdm/libs/core/fb/hw_primary.h
+++ b/sdm/libs/core/fb/hw_primary.h
@@ -44,7 +44,7 @@
   virtual DisplayError GetDisplayAttributes(uint32_t index,
                                             HWDisplayAttributes *display_attributes);
   virtual DisplayError SetDisplayAttributes(uint32_t index);
-  virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+  virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
   virtual DisplayError PowerOff();
   virtual DisplayError Doze();
   virtual DisplayError DozeSuspend();
diff --git a/sdm/libs/core/hw_interface.cpp b/sdm/libs/core/hw_interface.cpp
index f05aa0c..cfaf72b 100644
--- a/sdm/libs/core/hw_interface.cpp
+++ b/sdm/libs/core/hw_interface.cpp
@@ -38,7 +38,7 @@
 #ifdef COMPILE_DRM
 #include "drm/hw_device_drm.h"
 #include "drm/hw_virtual_drm.h"
-#include "drm/hw_hdmi_drm.h"
+#include "drm/hw_tv_drm.h"
 #endif
 
 #define __CLASS__ "HWInterface"
@@ -67,7 +67,7 @@
         hw = new HWHDMI(buffer_sync_handler, hw_info_intf);
       } else {
 #ifdef COMPILE_DRM
-        hw = new HWHDMIDRM(buffer_sync_handler, buffer_allocator, hw_info_intf);
+        hw = new HWTVDRM(buffer_sync_handler, buffer_allocator, hw_info_intf);
 #endif
       }
       break;
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index 616e3fb..6774159 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -83,7 +83,7 @@
   virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info) = 0;
   virtual DisplayError SetDisplayAttributes(uint32_t index) = 0;
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes) = 0;
-  virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index) = 0;
+  virtual DisplayError GetConfigIndex(char *mode, uint32_t *index) = 0;
   virtual DisplayError PowerOn() = 0;
   virtual DisplayError PowerOff() = 0;
   virtual DisplayError Doze() = 0;
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index 8e89784..f8909f4 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -212,7 +212,7 @@
   return kErrorNone;
 }
 
-DisplayError ResourceDefault::Stop(Handle display_ctx) {
+DisplayError ResourceDefault::Stop(Handle display_ctx, HWLayers *hw_layers) {
   locker_.Unlock();
 
   return kErrorNone;
diff --git a/sdm/libs/core/resource_default.h b/sdm/libs/core/resource_default.h
index 76d19f3..a67eb09 100644
--- a/sdm/libs/core/resource_default.h
+++ b/sdm/libs/core/resource_default.h
@@ -50,7 +50,7 @@
                                           const HWPanelInfo &hw_panel_info,
                                           const HWMixerAttributes &mixer_attributes);
   virtual DisplayError Start(Handle display_ctx);
-  virtual DisplayError Stop(Handle display_ctx);
+  virtual DisplayError Stop(Handle display_ctx, HWLayers *hw_layers);
   virtual DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
   virtual DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
   virtual DisplayError Commit(Handle display_ctx, HWLayers *hw_layers);
diff --git a/sdm/libs/utils/debug.cpp b/sdm/libs/utils/debug.cpp
index 592be68..60ce0ac 100644
--- a/sdm/libs/utils/debug.cpp
+++ b/sdm/libs/utils/debug.cpp
@@ -47,11 +47,14 @@
   return value;
 }
 
-int Debug::GetHDMIResolution() {
-  int value = 0;
-  debug_.debug_handler_->GetProperty("hw.hdmi.resolution", &value);
+bool Debug::GetExternalResolution(char *value) {
+  uint32_t retval = 0;
+  debug_.debug_handler_->GetProperty("hw.hdmi.resolution", value);
+  if (value[0]) {
+    retval = 1;
+  }
 
-  return value;
+  return retval;
 }
 
 void Debug::GetIdleTimeoutMs(uint32_t *active_ms, uint32_t *inactive_ms) {