Merge "libdebug: Fix order of DLOG definitions."
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 4123882..2aeb337 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -162,6 +162,24 @@
    */
   PLANE_SET_ROT_FB_ID,
   /*
+   * Op: Sets inverse pma mode on this plane.
+   * Arg: uint32_t - Plane ID
+   *      uint32_t - enable/disable inverse pma.
+   */
+  PLANE_SET_INVERSE_PMA,
+  /*
+   * Op: Sets csc config on this plane.
+   * Arg: uint32_t - Plane ID
+   *      uint64_t - Address of the csc config object(version based)
+   */
+  PLANE_SET_DGM_CSC_CONFIG,
+  /*
+   * Op: Sets SSPP Feature
+   * Arg: uint32_t - Plane ID
+   *      DRMPPFeatureInfo * - PP feature data pointer
+   */
+  PLANE_SET_POST_PROC,
+  /*
    * Op: Activate or deactivate a CRTC
    * Arg: uint32_t - CRTC ID
    *      uint32_t - 1 to enable, 0 to disable
@@ -454,6 +472,13 @@
   MAX,
 };
 
+enum struct DRMTonemapLutType {
+  DMA_1D_GC,
+  DMA_1D_IGC,
+  VIG_1D_IGC,
+  VIG_3D_GAMUT,
+};
+
 struct DRMPlaneTypeInfo {
   DRMPlaneType type;
   uint32_t master_plane_id;
@@ -471,6 +496,9 @@
   QSEEDStepVersion qseed3_version;
   bool multirect_prop_present = false;
   InlineRotationVersion inrot_version;  // inline rotation version
+  bool inverse_pma = false;
+  uint32_t dgm_csc_version = 0;  // csc used with DMA
+  std::map<DRMTonemapLutType, uint32_t> tonemap_lut_version_map = {};
 };
 
 // All DRM Planes as map<Plane_id , plane_type_info> listed from highest to lowest priority
@@ -550,6 +578,10 @@
   kFeaturePAMemColSky,
   kFeaturePAMemColFoliage,
   kFeaturePAMemColProt,
+  kFeatureDgmIgc,
+  kFeatureDgmGc,
+  kFeatureVigIgc,
+  kFeatureVigGamut,
   kPPFeaturesMax,
 };
 
diff --git a/sdm/include/private/color_params.h b/sdm/include/private/color_params.h
index 4f9513f..9a7f575 100644
--- a/sdm/include/private/color_params.h
+++ b/sdm/include/private/color_params.h
@@ -121,6 +121,13 @@
   kMaxNumPPFeatures,
 };
 
+enum PPSourceColorFeatureID {
+  kSourceColorFeatureIgc = kMaxNumPPFeatures + 1,
+  kSourceColorFeatureGc,
+  kSourceColorFeatureGamut,
+  kMaxNumSourcePPFeatures,
+};
+
 struct PPPendingParams {
   int32_t action = kNoAction;
   void *params = NULL;
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 5304133..c9b5782 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -168,8 +168,6 @@
   std::string device_path = "";
   float min_downscale = 2.0f;
   bool downscale_compression = false;
-
-  void Reset() { *this = HWRotatorInfo(); }
 };
 
 enum HWQseedStepVersion {
@@ -259,8 +257,6 @@
   HWQseedStepVersion pipe_qseed3_version = kQseed3v2;  // only valid when has_qseed3=true
   uint32_t min_prefill_lines = 0;
   InlineRotationVersion inrot_version = kInlineRotationNone;
-
-  void Reset() { *this = HWResourceInfo(); }
 };
 
 struct HWSplitInfo {
@@ -356,8 +352,8 @@
 };
 
 struct HWSessionConfig {
-  LayerRect src_rect;
-  LayerRect dst_rect;
+  LayerRect src_rect {};
+  LayerRect dst_rect {};
   uint32_t buffer_count = 0;
   bool secure = false;
   uint32_t frame_rate = 0;
@@ -388,21 +384,19 @@
 struct HWRotateInfo {
   int pipe_id = -1;  // Not actual pipe id, but the relative DMA id
   int writeback_id = -1;  // Writeback block id, but this is the same as DMA id
-  LayerRect src_roi;  // Source crop of each split
-  LayerRect dst_roi;  // Destination crop of each split
+  LayerRect src_roi {};  // Source crop of each split
+  LayerRect dst_roi {};  // Destination crop of each split
   bool valid = false;
   int rotate_id = -1;  // Actual rotator session id with driver
-
-  void Reset() { *this = HWRotateInfo(); }
 };
 
 struct HWRotatorSession {
-  HWRotateInfo hw_rotate_info[kMaxRotatePerLayer];
+  HWRotateInfo hw_rotate_info[kMaxRotatePerLayer] {};
   uint32_t hw_block_count = 0;  // number of rotator hw blocks used by rotator session
   int session_id = -1;  // A handle with Session Manager
-  HWSessionConfig hw_session_config;
-  LayerBuffer input_buffer;  // Input to rotator
-  LayerBuffer output_buffer;  // Output of rotator, crop width and stride are same
+  HWSessionConfig hw_session_config {};
+  LayerBuffer input_buffer {};  // Input to rotator
+  LayerBuffer output_buffer {};  // Output of rotator, crop width and stride are same
   float input_compression = 1.0f;
   float output_compression = 1.0f;
   bool is_buffer_cached = false;
@@ -442,10 +436,10 @@
   int32_t phase_step_x = 0;
   int32_t init_phase_y = 0;
   int32_t phase_step_y = 0;
-  HWPixelExtension left;
-  HWPixelExtension top;
-  HWPixelExtension right;
-  HWPixelExtension bottom;
+  HWPixelExtension left {};
+  HWPixelExtension top {};
+  HWPixelExtension right {};
+  HWPixelExtension bottom {};
   uint32_t roi_width = 0;
   int32_t preload_x = 0;
   int32_t preload_y = 0;
@@ -461,7 +455,7 @@
   } enable;
   uint32_t dst_width = 0;
   uint32_t dst_height = 0;
-  HWPlane plane[MAX_PLANES];
+  HWPlane plane[MAX_PLANES] {};
   // scale_v2_data fields
   ScalingFilterConfig y_rgb_filter_cfg = kFilterEdgeDirected;
   ScalingFilterConfig uv_filter_cfg = kFilterEdgeDirected;
@@ -483,8 +477,7 @@
   uint32_t uv_cir_lut_idx = 0;
   uint32_t y_rgb_sep_lut_idx = 0;
   uint32_t uv_sep_lut_idx = 0;
-
-  HWDetailEnhanceData detail_enhance;
+  HWDetailEnhanceData detail_enhance {};
 };
 
 struct HWDestScaleInfo {
@@ -507,18 +500,16 @@
   uint8_t rect = 255;
   uint32_t pipe_id = 0;
   HWSubBlockType sub_block_type = kHWSubBlockMax;
-  LayerRect src_roi;
-  LayerRect dst_roi;
-  LayerRect excl_rect;  // exclusion rectangle per pipe rectangle
+  LayerRect src_roi {};
+  LayerRect dst_roi {};
+  LayerRect excl_rect {};  // exclusion rectangle per pipe rectangle
   uint8_t horizontal_decimation = 0;
   uint8_t vertical_decimation = 0;
-  HWScaleData scale_data;
+  HWScaleData scale_data {};
   uint32_t z_order = 0;
   uint8_t flags = 0;
   bool valid = false;
   bool is_virtual = 0;
-
-  void Reset() { *this = HWPipeInfo(); }
 };
 
 struct HWSolidfillStage {
@@ -530,15 +521,12 @@
 };
 
 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;
-
+  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(); }
 };
 
 struct HWHDRLayerInfo {
@@ -560,19 +548,15 @@
   LayerStack *stack = NULL;        // Input layer stack. Set by the caller.
   uint32_t app_layer_count = 0;    // Total number of app layers. Must not be 0.
   uint32_t gpu_target_index = 0;   // GPU target layer index. 0 if not present.
-
   std::vector<Layer> hw_layers = {};  // Layers which need to be programmed on the HW
   std::vector<LayerExt> layer_exts = {};  // Extention layer having list of
                                           // exclusion rectangles for each layer
-
-  std::vector<uint32_t> index;   // Indexes of the layers from the layer stack which need to
+  std::vector<uint32_t> index {};   // Indexes of the layers from the layer stack which need to
                                  // be programmed on hardware.
-  std::vector<uint32_t> roi_index;  // Stores the ROI index where the layers are visible.
-
+  std::vector<uint32_t> roi_index {};  // Stores the ROI index where the layers are visible.
   int sync_handle = -1;         // Release fence id for current draw cycle.
   int set_idle_time_ms = -1;    // Set idle time to the new specified value.
                                 //    -1 indicates no change in idle time since last set value.
-
   std::vector<LayerRect> left_frame_roi = {};   // Left ROI.
   std::vector<LayerRect> right_frame_roi = {};  // Right ROI.
   LayerRect partial_fb_roi = {};   // Damaged area in framebuffer.
@@ -596,8 +580,8 @@
 };
 
 struct HWLayers {
-  HWLayersInfo info;
-  HWLayerConfig config[kMaxSDELayers];
+  HWLayersInfo info {};
+  HWLayerConfig config[kMaxSDELayers] {};
   float output_compression = 1.0f;
   HWQosData qos_data = {};
   HWAVRInfo hw_avr_info = {};
@@ -610,12 +594,10 @@
   uint32_t v_pulse_width = 0;  //!< Vertical pulse width of panel
   uint32_t h_total = 0;        //!< Total width of panel (hActive + hFP + hBP + hPulseWidth)
   uint32_t v_total = 0;        //!< Total height of panel (vActive + vFP + vBP + vPulseWidth)
-  std::bitset<32> s3d_config;  //!< Stores the bit mask of S3D modes
+  std::bitset<32> s3d_config {};  //!< Stores the bit mask of S3D modes
   uint32_t clock_khz = 0;      //!< Stores the pixel clock of panel in khz
   HWTopology topology = kUnknown;  //!< Stores the topology information.
 
-  void Reset() { *this = HWDisplayAttributes(); }
-
   bool operator !=(const HWDisplayAttributes &display_attributes) {
     return ((is_device_split != display_attributes.is_device_split) ||
             (x_pixels != display_attributes.x_pixels) ||
diff --git a/sdm/libs/core/drm/hw_color_manager_drm.cpp b/sdm/libs/core/drm/hw_color_manager_drm.cpp
index 85e9574..af9e145 100644
--- a/sdm/libs/core/drm/hw_color_manager_drm.cpp
+++ b/sdm/libs/core/drm/hw_color_manager_drm.cpp
@@ -29,6 +29,11 @@
 
 #define __CLASS__ "HWColorManagerDRM"
 
+#include <array>
+#include <map>
+#include <cstring>
+#include <vector>
+
 #ifdef PP_DRM_ENABLE
 #include <drm/msm_drm_pp.h>
 #endif
@@ -72,33 +77,67 @@
 static const uint32_t kMemColorSkinMask = (1 << 19);
 static const uint32_t kMemColorSkyMask = (1 << 20);
 static const uint32_t kMemColorFolMask = (1 << 21);
+
+static const uint32_t kSourceFeatureV5 = 5;
 #endif
 #endif
 
 namespace sdm {
 
-DisplayError (*HWColorManagerDrm::GetDrmFeature[])(const PPFeatureInfo &, DRMPPFeatureInfo *) = {
-        [kFeaturePcc] = &HWColorManagerDrm::GetDrmPCC,
-        [kFeatureIgc] = &HWColorManagerDrm::GetDrmIGC,
-        [kFeaturePgc] = &HWColorManagerDrm::GetDrmPGC,
-        [kFeatureMixerGc] = &HWColorManagerDrm::GetDrmMixerGC,
-        [kFeaturePaV2] = NULL,
-        [kFeatureDither] = &HWColorManagerDrm::GetDrmDither,
-        [kFeatureGamut] = &HWColorManagerDrm::GetDrmGamut,
-        [kFeaturePADither] = &HWColorManagerDrm::GetDrmPADither,
-        [kFeaturePAHsic] = &HWColorManagerDrm::GetDrmPAHsic,
-        [kFeaturePASixZone] = &HWColorManagerDrm::GetDrmPASixZone,
-        [kFeaturePAMemColSkin] = &HWColorManagerDrm::GetDrmPAMemColSkin,
-        [kFeaturePAMemColSky] = &HWColorManagerDrm::GetDrmPAMemColSky,
-        [kFeaturePAMemColFoliage] = &HWColorManagerDrm::GetDrmPAMemColFoliage,
-        [kFeaturePAMemColProt] = &HWColorManagerDrm::GetDrmPAMemColProt,
+typedef std::map<uint32_t, std::vector<DRMPPFeatureID>> DrmPPFeatureMap;
+
+static const DrmPPFeatureMap g_dspp_map = {
+  {kGlobalColorFeaturePcc,      {kFeaturePcc}},
+  {kGlobalColorFeatureIgc,      {kFeatureIgc}},
+  {kGlobalColorFeaturePgc,      {kFeaturePgc}},
+  {kMixerColorFeatureGc,        {kFeatureMixerGc}},
+  {kGlobalColorFeaturePaV2,     {kFeaturePAHsic,
+                                 kFeaturePASixZone,
+                                 kFeaturePAMemColSkin,
+                                 kFeaturePAMemColSky,
+                                 kFeaturePAMemColFoliage,
+                                 kFeaturePAMemColProt}},
+  {kGlobalColorFeatureDither,   {kFeatureDither}},
+  {kGlobalColorFeatureGamut,    {kFeatureGamut}},
+  {kGlobalColorFeaturePADither, {kFeaturePADither}},
 };
 
-void HWColorManagerDrm::FreeDrmFeatureData(DRMPPFeatureInfo *feature) {
-  if (feature->payload)
-    free(feature->payload);
-  feature->payload = NULL;
-}
+static const DrmPPFeatureMap g_vig_map = {
+  {kSourceColorFeatureIgc,      {kFeatureVigIgc}},
+  {kSourceColorFeatureGamut,    {kFeatureVigGamut}},
+};
+
+static const DrmPPFeatureMap g_dgm_map = {
+  {kSourceColorFeatureIgc,      {kFeatureDgmIgc}},
+  {kSourceColorFeatureGc,       {kFeatureDgmGc}},
+};
+
+static const std::array<const DrmPPFeatureMap *,
+                        static_cast<int>(kPPBlockMax)> feature_map_list = {
+  {&g_dspp_map, &g_vig_map, &g_dgm_map}
+};
+
+DisplayError (*HWColorManagerDrm::pp_features_[])(const PPFeatureInfo &,
+                                                    DRMPPFeatureInfo *) = {
+  [kFeaturePcc] = &HWColorManagerDrm::GetDrmPCC,
+  [kFeatureIgc] = &HWColorManagerDrm::GetDrmIGC,
+  [kFeaturePgc] = &HWColorManagerDrm::GetDrmPGC,
+  [kFeatureMixerGc] = &HWColorManagerDrm::GetDrmMixerGC,
+  [kFeaturePaV2] = NULL,
+  [kFeatureDither] = &HWColorManagerDrm::GetDrmDither,
+  [kFeatureGamut] = &HWColorManagerDrm::GetDrmGamut,
+  [kFeaturePADither] = &HWColorManagerDrm::GetDrmPADither,
+  [kFeaturePAHsic] = &HWColorManagerDrm::GetDrmPAHsic,
+  [kFeaturePASixZone] = &HWColorManagerDrm::GetDrmPASixZone,
+  [kFeaturePAMemColSkin] = &HWColorManagerDrm::GetDrmPAMemColSkin,
+  [kFeaturePAMemColSky] = &HWColorManagerDrm::GetDrmPAMemColSky,
+  [kFeaturePAMemColFoliage] = &HWColorManagerDrm::GetDrmPAMemColFoliage,
+  [kFeaturePAMemColProt] = &HWColorManagerDrm::GetDrmPAMemColProt,
+  [kFeatureDgmIgc] = &HWColorManagerDrm::GetDrmIGC,
+  [kFeatureDgmGc] = &HWColorManagerDrm::GetDrmPGC,
+  [kFeatureVigIgc] = &HWColorManagerDrm::GetDrmIGC,
+  [kFeatureVigGamut] = &HWColorManagerDrm::GetDrmGamut,
+};
 
 uint32_t HWColorManagerDrm::GetFeatureVersion(const DRMPPFeatureInfo &feature) {
   uint32_t version = PPFeatureVersion::kSDEPpVersionInvalid;
@@ -149,40 +188,146 @@
   return version;
 }
 
-DRMPPFeatureID HWColorManagerDrm::ToDrmFeatureId(uint32_t id) {
-  DRMPPFeatureID ret = kPPFeaturesMax;
-
-  switch (id) {
-    case kGlobalColorFeaturePcc:
-      ret = kFeaturePcc;
-      break;
-    case kGlobalColorFeatureIgc:
-      ret = kFeatureIgc;
-      break;
-    case kGlobalColorFeaturePgc:
-      ret = kFeaturePgc;
-      break;
-    case kMixerColorFeatureGc:
-      ret = kFeatureMixerGc;
-      break;
-    case kGlobalColorFeaturePaV2:
-      ret = kFeaturePAHsic;
-      break;
-    case kGlobalColorFeatureDither:
-      ret = kFeatureDither;
-      break;
-    case kGlobalColorFeatureGamut:
-      ret = kFeatureGamut;
-      break;
-    case kGlobalColorFeaturePADither:
-      ret = kFeaturePADither;
-      break;
-    default:
-      break;
+DisplayError HWColorManagerDrm::ToDrmFeatureId(PPBlock block, uint32_t id,
+  std::vector<DRMPPFeatureID> *drm_id) {
+  if (block < kDSPP || block >= kPPBlockMax) {
+    DLOGE("Invalid input parameter, block = %d", (int) block);
+    return kErrorParameters;
   }
+
+  if (!drm_id) {
+    DLOGE("Invalid output parameter, block = %d", (int) block);
+    return kErrorParameters;
+  }
+
+  auto map = feature_map_list[block];
+  auto drm_features = map->find(id);
+  if (drm_features == map->end()) {
+    return kErrorParameters;
+  }
+  for (DRMPPFeatureID fid : drm_features->second)
+    drm_id->push_back(fid);
+
+  return kErrorNone;
+}
+
+DisplayError HWColorManagerDrm::GetDrmFeature(PPFeatureInfo *in_data,
+                                              DRMPPFeatureInfo *out_data,
+                                              bool force_disable) {
+  DisplayError ret = kErrorParameters;
+  uint32_t flags = 0;
+
+  if (!in_data || !out_data) {
+    DLOGE("Invalid input parameter, in_data or out_data is NULL");
+    return ret;
+  }
+
+  /* Cache and override the enable_flags_ if force_disable is requested */
+  if (force_disable) {
+    flags = in_data->enable_flags_;
+    in_data->enable_flags_ = kOpsDisable;
+  }
+
+  if (pp_features_[out_data->id])
+    ret = pp_features_[out_data->id](*in_data, out_data);
+
+
+  /* Restore the original enable_flags_ */
+  if (force_disable) {
+    in_data->enable_flags_ = flags;
+  }
+
   return ret;
 }
 
+void HWColorManagerDrm::FreeDrmFeatureData(DRMPPFeatureInfo *feature) {
+  if (feature && feature->payload) {
+#ifdef PP_DRM_ENABLE
+    void *ptr = feature->payload;
+#endif
+
+    switch (feature->id) {
+      case kFeaturePcc: {
+#ifdef PP_DRM_ENABLE
+        drm_msm_pcc *pcc = reinterpret_cast<drm_msm_pcc *>(ptr);
+        delete pcc;
+#endif
+        break;
+      }
+      case kFeatureIgc:
+      case kFeatureDgmIgc:
+      case kFeatureVigIgc: {
+#ifdef PP_DRM_ENABLE
+        drm_msm_igc_lut *igc = reinterpret_cast<drm_msm_igc_lut *>(ptr);
+        delete igc;
+#endif
+        break;
+      }
+      case kFeaturePgc:
+      case kFeatureDgmGc: {
+#ifdef PP_DRM_ENABLE
+        drm_msm_pgc_lut *pgc = reinterpret_cast<drm_msm_pgc_lut *>(ptr);
+        delete pgc;
+#endif
+        break;
+      }
+      case kFeatureDither: {
+#ifdef PP_DRM_ENABLE
+        drm_msm_dither *dither = reinterpret_cast<drm_msm_dither *>(ptr);
+        delete dither;
+#endif
+        break;
+      }
+      case kFeatureGamut:
+      case kFeatureVigGamut: {
+#ifdef PP_DRM_ENABLE
+        drm_msm_3d_gamut *gamut = reinterpret_cast<drm_msm_3d_gamut *>(ptr);
+        delete gamut;
+#endif
+        break;
+      }
+      case kFeaturePADither: {
+#if defined(PP_DRM_ENABLE) && defined(DRM_MSM_PA_DITHER)
+        drm_msm_pa_dither *pa_dither = reinterpret_cast<drm_msm_pa_dither *>(ptr);
+        delete pa_dither;
+#endif
+        break;
+      }
+      case kFeaturePAHsic: {
+#if defined(PP_DRM_ENABLE) && defined(DRM_MSM_PA_HSIC)
+        drm_msm_pa_hsic *hsic = reinterpret_cast<drm_msm_pa_hsic *>(ptr);
+        delete hsic;
+#endif
+        break;
+      }
+      case kFeaturePASixZone: {
+#if defined(PP_DRM_ENABLE) && defined(DRM_MSM_SIXZONE)
+        drm_msm_sixzone *sixzone = reinterpret_cast<drm_msm_sixzone *>(ptr);
+        delete sixzone;
+#endif
+        break;
+      }
+      case kFeaturePAMemColSkin:
+      case kFeaturePAMemColSky:
+      case kFeaturePAMemColFoliage:
+      case kFeaturePAMemColProt: {
+#if defined(PP_DRM_ENABLE) && defined(DRM_MSM_MEMCOL)
+        drm_msm_memcol *memcol = reinterpret_cast<drm_msm_memcol *>(ptr);
+        delete memcol;
+#endif
+        break;
+      }
+      case kFeatureMixerGc:
+      case kFeaturePaV2:
+      default: {
+        DLOGE("Invalid feature: %d\n", feature->id);
+        return;
+      }
+    }
+    feature->payload = nullptr;
+  }
+}
+
 DisplayError HWColorManagerDrm::GetDrmPCC(const PPFeatureInfo &in_data,
                                           DRMPPFeatureInfo *out_data) {
   DisplayError ret = kErrorNone;
@@ -193,11 +338,6 @@
   struct drm_msm_pcc_coeff *mdp_pcc_coeffs = NULL;
   uint32_t i = 0;
 
-  if (!out_data) {
-    DLOGE("Invalid input parameter for pcc");
-    return kErrorParameters;
-  }
-
   switch (in_data.feature_version_) {
   case PPFeatureVersion::kSDEPccV4:
     sde_pcc = (struct SDEPccV4Cfg *) in_data.GetConfigData();
@@ -207,7 +347,6 @@
     return kErrorParameters;
   }
 
-  out_data->id = kFeaturePcc;
   out_data->type = sde_drm::kPropBlob;
   out_data->version = in_data.feature_version_;
   out_data->payload_size = sizeof(struct drm_msm_pcc);
@@ -276,14 +415,9 @@
   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:
+  case kSourceFeatureV5:
     sde_igc = (struct SDEIgcV30LUTData *) in_data.GetConfigData();
     break;
   default:
@@ -291,7 +425,6 @@
     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);
@@ -341,12 +474,8 @@
   struct SDEPgcLUTData *sde_pgc;
   struct drm_msm_pgc_lut *mdp_pgc;
 
-  if (!out_data) {
-    DLOGE("Invalid input parameter for gamut");
-    return kErrorParameters;
-  }
   sde_pgc = (struct SDEPgcLUTData *)in_data.GetConfigData();
-  out_data->id = kFeaturePgc;
+
   out_data->type = sde_drm::kPropBlob;
   out_data->version = in_data.feature_version_;
   out_data->payload_size = sizeof(struct drm_msm_pgc_lut);
@@ -366,7 +495,8 @@
     return kErrorMemory;
   }
 
-  if (in_data.enable_flags_ & kOpsEnable)
+  if ((in_data.enable_flags_ & kOpsEnable) &&
+      (in_data.feature_id_ == kGlobalColorFeaturePgc))
     mdp_pgc->flags = PGC_8B_ROUND;
   else
     mdp_pgc->flags = 0;
@@ -388,11 +518,6 @@
                                               DRMPPFeatureInfo *out_data) {
   DisplayError ret = kErrorNone;
 #ifdef PP_DRM_ENABLE
-  if (!out_data) {
-    DLOGE("Invalid input parameter for Mixer GC");
-    return kErrorParameters;
-  }
-
   out_data->id = kPPFeaturesMax;
   out_data->type = sde_drm::kPropBlob;
   out_data->version = in_data.feature_version_;
@@ -407,14 +532,8 @@
   struct SDEPaData *sde_pa;
   struct drm_msm_pa_hsic *mdp_hsic;
 
-  if (!out_data) {
-    DLOGE("Invalid input parameter for pa hsic");
-    return kErrorParameters;
-  }
-
   sde_pa = (struct SDEPaData *) in_data.GetConfigData();
 
-  out_data->id = kFeaturePAHsic;
   out_data->type = sde_drm::kPropBlob;
   out_data->version = in_data.feature_version_;
   out_data->payload_size = 0;
@@ -477,14 +596,8 @@
 #if defined(PP_DRM_ENABLE) && defined(DRM_MSM_SIXZONE)
   struct SDEPaData *sde_pa;
 
-  if (!out_data) {
-    DLOGE("Invalid input parameter for six zone");
-    return kErrorParameters;
-  }
-
   sde_pa = (struct SDEPaData *) in_data.GetConfigData();
 
-  out_data->id = kFeaturePASixZone;
   out_data->type = sde_drm::kPropBlob;
   out_data->version = in_data.feature_version_;
   out_data->payload_size = 0;
@@ -558,14 +671,8 @@
 #if defined(PP_DRM_ENABLE) && defined(DRM_MSM_MEMCOL)
   struct SDEPaData *sde_pa;
 
-  if (!out_data) {
-    DLOGE("Invalid input parameter for memory color skin");
-    return kErrorParameters;
-  }
-
   sde_pa = (struct SDEPaData *) in_data.GetConfigData();
 
-  out_data->id = kFeaturePAMemColSkin;
   out_data->type = sde_drm::kPropBlob;
   out_data->version = in_data.feature_version_;
   out_data->payload_size = 0;
@@ -621,14 +728,8 @@
 #if defined(PP_DRM_ENABLE) && defined(DRM_MSM_MEMCOL)
   struct SDEPaData *sde_pa;
 
-  if (!out_data) {
-    DLOGE("Invalid input parameter for memory color sky");
-    return kErrorParameters;
-  }
-
   sde_pa = (struct SDEPaData *) in_data.GetConfigData();
 
-  out_data->id = kFeaturePAMemColSky;
   out_data->type = sde_drm::kPropBlob;
   out_data->version = in_data.feature_version_;
   out_data->payload_size = 0;
@@ -684,14 +785,8 @@
 #if defined(PP_DRM_ENABLE) && defined(DRM_MSM_MEMCOL)
   struct SDEPaData *sde_pa;
 
-  if (!out_data) {
-    DLOGE("Invalid input parameter for memory color foliage");
-    return kErrorParameters;
-  }
-
   sde_pa = (struct SDEPaData *) in_data.GetConfigData();
 
-  out_data->id = kFeaturePAMemColFoliage;
   out_data->type = sde_drm::kPropBlob;
   out_data->version = in_data.feature_version_;
   out_data->payload_size = 0;
@@ -748,14 +843,8 @@
   struct SDEPaData *sde_pa;
   struct drm_msm_memcol *mdp_memcol;
 
-  if (!out_data) {
-    DLOGE("Invalid input parameter for memory color prot");
-    return kErrorParameters;
-  }
-
   sde_pa = (struct SDEPaData *) in_data.GetConfigData();
 
-  out_data->id = kFeaturePAMemColProt;
   out_data->type = sde_drm::kPropBlob;
   out_data->version = in_data.feature_version_;
   out_data->payload_size = sizeof(struct drm_msm_memcol);
@@ -800,13 +889,7 @@
   struct SDEDitherCfg *sde_dither = NULL;
   struct drm_msm_dither *mdp_dither = NULL;
 
-  if (!out_data) {
-    DLOGE("Invalid input parameter for dither");
-    return kErrorParameters;
-  }
-
   sde_dither = (struct SDEDitherCfg *)in_data.GetConfigData();
-  out_data->id = kFeatureDither;
   out_data->type = sde_drm::kPropBlob;
   out_data->version = in_data.feature_version_;
   out_data->payload_size = sizeof(struct drm_msm_dither);
@@ -846,12 +929,8 @@
   struct drm_msm_3d_gamut *mdp_gamut = NULL;
   uint32_t size = 0;
 
-  if (!out_data) {
-    DLOGE("Invalid input parameter for gamut");
-    return kErrorParameters;
-  }
   sde_gamut = (struct SDEGamutCfg *)in_data.GetConfigData();
-  out_data->id = kFeatureGamut;
+
   out_data->type = sde_drm::kPropBlob;
   out_data->version = in_data.feature_version_;
   out_data->payload_size = sizeof(struct drm_msm_3d_gamut);
@@ -921,12 +1000,6 @@
   struct SDEPADitherData* sde_dither;
   struct drm_msm_pa_dither* mdp_dither;
 
-  if (!out_data) {
-    DLOGE("Invalid input parameter for PA dither");
-    return kErrorParameters;
-  }
-
-  out_data->id = kFeaturePADither;
   out_data->type = sde_drm::kPropBlob;
   out_data->version = in_data.feature_version_;
 
diff --git a/sdm/libs/core/drm/hw_color_manager_drm.h b/sdm/libs/core/drm/hw_color_manager_drm.h
index 1e77f6c..66415e0 100644
--- a/sdm/libs/core/drm/hw_color_manager_drm.h
+++ b/sdm/libs/core/drm/hw_color_manager_drm.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -33,7 +33,6 @@
 #include <drm_interface.h>
 #include <private/color_params.h>
 #include <vector>
-#include <map>
 
 using sde_drm::DRMPPFeatureID;
 using sde_drm::DRMPPFeatureInfo;
@@ -53,36 +52,32 @@
 using sde_drm::kFeaturePAMemColFoliage;
 using sde_drm::kFeaturePAMemColProt;
 using sde_drm::kPPFeaturesMax;
+using sde_drm::kFeatureDgmIgc;
+using sde_drm::kFeatureDgmGc;
+using sde_drm::kFeatureVigIgc;
+using sde_drm::kFeatureVigGamut;
 
 namespace sdm {
 
-typedef std::map<uint32_t, std::vector<uint32_t>> DrmPPFeatureMap;
-
-static const DrmPPFeatureMap DrmPPfeatureMap_ = \
-  {{kGlobalColorFeaturePcc, {kFeaturePcc}},
-    {kGlobalColorFeatureIgc, {kFeatureIgc}},
-    {kGlobalColorFeaturePgc, {kFeaturePgc}},
-    {kMixerColorFeatureGc, {kMixerColorFeatureGc}},
-    {kGlobalColorFeaturePaV2, {kFeaturePAHsic, kFeaturePASixZone,
-                               kFeaturePAMemColSkin, kFeaturePAMemColSky,
-                               kFeaturePAMemColFoliage, kFeaturePAMemColProt}},
-    {kGlobalColorFeatureDither, {kFeatureDither}},
-    {kGlobalColorFeatureGamut, {kFeatureGamut}},
-    {kGlobalColorFeaturePADither, {kFeaturePADither}},
-};
-
 static const uint32_t kMaxPCCChanel = 3;
 
+enum PPBlock {
+  kDSPP,
+  kVIG,
+  kDGM,
+  kPPBlockMax,
+};
+
 class HWColorManagerDrm {
  public:
-  static DisplayError (*GetDrmFeature[kPPFeaturesMax])(const PPFeatureInfo &in_data,
-                                                          DRMPPFeatureInfo *out_data);
-  static void FreeDrmFeatureData(DRMPPFeatureInfo *feature);
-  static uint32_t GetFeatureVersion(const DRMPPFeatureInfo &feature);
-  static DRMPPFeatureID ToDrmFeatureId(uint32_t id);
-
- protected:
+  DisplayError GetDrmFeature(PPFeatureInfo *in_data, DRMPPFeatureInfo *out_data,
+                             bool force_disable = false);
+  void FreeDrmFeatureData(DRMPPFeatureInfo *feature);
+  uint32_t GetFeatureVersion(const DRMPPFeatureInfo &feature);
+  DisplayError ToDrmFeatureId(const PPBlock block, const uint32_t id,
+                              std::vector<DRMPPFeatureID> *drm_id);
   HWColorManagerDrm() {}
+  ~HWColorManagerDrm() {}
 
  private:
   static DisplayError GetDrmPCC(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
@@ -99,6 +94,9 @@
   static DisplayError GetDrmPAMemColFoliage(const PPFeatureInfo &in_data,
                                             DRMPPFeatureInfo *out_data);
   static DisplayError GetDrmPAMemColProt(const PPFeatureInfo &in_data, DRMPPFeatureInfo *out_data);
+
+  static DisplayError (*pp_features_[kPPFeaturesMax])(const PPFeatureInfo &in_data,
+                                                      DRMPPFeatureInfo *out_data);
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index b9765c8..fa413bb 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -61,7 +61,6 @@
 
 #include "hw_device_drm.h"
 #include "hw_info_interface.h"
-#include "hw_color_manager_drm.h"
 
 #define __CLASS__ "HWDeviceDRM"
 
@@ -382,6 +381,9 @@
     hw_scale_ = new HWScaleDRM(HWScaleDRM::Version::V2);
   }
 
+  std::unique_ptr<HWColorManagerDrm> hw_color_mgr(new HWColorManagerDrm());
+  hw_color_mgr_ = std::move(hw_color_mgr);
+
   return kErrorNone;
 }
 
@@ -739,15 +741,19 @@
     return kErrorNone;
   }
 
+  int64_t release_fence_t = -1;
   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);
+  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence_t);
+
   int ret = drm_atomic_intf_->Commit(true /* synchronous */, true /* retain_planes */);
   if (ret) {
     DLOGE("Failed with error: %d", ret);
     return kErrorHardware;
   }
-  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, release_fence);
 
+  *release_fence = static_cast<int>(release_fence_t);
+  DLOGD_IF(kTagDriverConfig, "RELEASE fence created: fd:%d", *release_fence);
   return kErrorNone;
 }
 
@@ -771,32 +777,38 @@
 
 DisplayError HWDeviceDRM::Doze(int *release_fence) {
   DTRACE_SCOPED();
+
+  int64_t release_fence_t = -1;
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
   drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::DOZE);
+  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence_t);
   int ret = drm_atomic_intf_->Commit(true /* synchronous */, true /* retain_planes */);
   if (ret) {
     DLOGE("Failed with error: %d", ret);
     return kErrorHardware;
   }
 
-  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, release_fence);
-
+  *release_fence = static_cast<int>(release_fence_t);
+  DLOGD_IF(kTagDriverConfig, "RELEASE fence created: fd:%d", *release_fence);
   return kErrorNone;
 }
 
 DisplayError HWDeviceDRM::DozeSuspend(int *release_fence) {
   DTRACE_SCOPED();
+
+  int64_t release_fence_t = -1;
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
   drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id,
                             DRMPowerMode::DOZE_SUSPEND);
+  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence_t);
   int ret = drm_atomic_intf_->Commit(true /* synchronous */, true /* retain_planes */);
   if (ret) {
     DLOGE("Failed with error: %d", ret);
     return kErrorHardware;
   }
 
-  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, release_fence);
-
+  *release_fence = static_cast<int>(release_fence_t);
+  DLOGD_IF(kTagDriverConfig, "RELEASE fence created: fd:%d", *release_fence);
   return kErrorNone;
 }
 
@@ -956,6 +968,11 @@
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ROT_CLK, token_.crtc_id, qos_data.rot_clock_hz);
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_SECURITY_LEVEL, token_.crtc_id, crtc_security_level);
 
+  if (!validate) {
+    drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence_);
+    drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE, token_.conn_id, &retire_fence_);
+  }
+
   DLOGI_IF(kTagDriverConfig, "%s::%s System Clock=%d Hz, Core: AB=%llu Bps, IB=%llu Bps, " \
            "LLCC: AB=%llu Bps, IB=%llu Bps, DRAM AB=%llu Bps, IB=%llu Bps, "\
            "Rot: Bw=%llu Bps, Clock=%d Hz", validate ? "Validate" : "Commit", device_name_,
@@ -1125,11 +1142,10 @@
     return kErrorHardware;
   }
 
-  int release_fence = -1;
-  int retire_fence = -1;
-
-  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence);
-  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE, token_.conn_id, &retire_fence);
+  int release_fence = static_cast<int>(release_fence_);
+  int retire_fence = static_cast<int>(retire_fence_);
+  DLOGD_IF(kTagDriverConfig, "RELEASE fence created: fd:%d", release_fence);
+  DLOGD_IF(kTagDriverConfig, "RETIRE fence created: fd:%d", retire_fence);
 
   HWLayersInfo &hw_layer_info = hw_layers->info;
   LayerStack *stack = hw_layer_info.stack;
@@ -1279,14 +1295,21 @@
 
 DisplayError HWDeviceDRM::GetPPFeaturesVersion(PPFeatureVersion *vers) {
   struct DRMPPFeatureInfo info = {};
+
+  if (!hw_color_mgr_)
+    return kErrorNotSupported;
+
   for (uint32_t i = 0; i < kMaxNumPPFeatures; i++) {
+    std::vector<DRMPPFeatureID> drm_id = {};
     memset(&info, 0, sizeof(struct DRMPPFeatureInfo));
-    info.id = HWColorManagerDrm::ToDrmFeatureId(i);
-    if (info.id >= sde_drm::kPPFeaturesMax)
+    hw_color_mgr_->ToDrmFeatureId(kDSPP, i, &drm_id);
+    if (drm_id.empty())
       continue;
 
+    info.id = drm_id.at(0);
+
     drm_mgr_intf_->GetCrtcPPInfo(token_.crtc_id, &info);
-    vers->version[i] = HWColorManagerDrm::GetFeatureVersion(info);
+    vers->version[i] = hw_color_mgr_->GetFeatureVersion(info);
   }
   return kErrorNone;
 }
@@ -1294,37 +1317,40 @@
 DisplayError HWDeviceDRM::SetPPFeatures(PPFeaturesConfig *feature_list) {
   int ret = 0;
   PPFeatureInfo *feature = NULL;
-  DRMPPFeatureInfo kernel_params = {};
-  bool crtc_feature = true;
+
+  if (!hw_color_mgr_)
+    return kErrorNotSupported;
 
   while (true) {
-    crtc_feature = true;
+    std::vector<DRMPPFeatureID> drm_id = {};
+    DRMPPFeatureInfo kernel_params = {};
+    bool crtc_feature = true;
+
     ret = feature_list->RetrieveNextFeature(&feature);
     if (ret)
       break;
-    kernel_params.id = HWColorManagerDrm::ToDrmFeatureId(feature->feature_id_);
+
+    hw_color_mgr_->ToDrmFeatureId(kDSPP, feature->feature_id_, &drm_id);
+    if (drm_id.empty())
+      continue;
+
+    kernel_params.id = drm_id.at(0);
     drm_mgr_intf_->GetCrtcPPInfo(token_.crtc_id, &kernel_params);
     if (kernel_params.version == std::numeric_limits<uint32_t>::max())
         crtc_feature = false;
     if (feature) {
       DLOGV_IF(kTagDriverConfig, "feature_id = %d", feature->feature_id_);
-      auto drm_features = DrmPPfeatureMap_.find(feature->feature_id_);
-      if (drm_features == DrmPPfeatureMap_.end()) {
-        DLOGE("DrmFeatures not valid for feature %d", feature->feature_id_);
-        continue;
-      }
+      for (DRMPPFeatureID id : drm_id) {
+        kernel_params.id = id;
+        ret = hw_color_mgr_->GetDrmFeature(feature, &kernel_params);
+        if (!ret && crtc_feature)
+          drm_atomic_intf_->Perform(DRMOps::CRTC_SET_POST_PROC,
+                                    token_.crtc_id, &kernel_params);
+        else if (!ret && !crtc_feature)
+          drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POST_PROC,
+                                    token_.conn_id, &kernel_params);
 
-      for (uint32_t drm_feature : drm_features->second) {
-        if (!HWColorManagerDrm::GetDrmFeature[drm_feature]) {
-          DLOGE("GetDrmFeature is not valid for DRM feature %d", drm_feature);
-          continue;
-        }
-        ret = HWColorManagerDrm::GetDrmFeature[drm_feature](*feature, &kernel_params);
-      if (!ret && crtc_feature)
-        drm_atomic_intf_->Perform(DRMOps::CRTC_SET_POST_PROC, token_.crtc_id, &kernel_params);
-      else if (!ret && !crtc_feature)
-        drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POST_PROC, token_.conn_id, &kernel_params);
-      HWColorManagerDrm::FreeDrmFeatureData(&kernel_params);
+        hw_color_mgr_->FreeDrmFeatureData(&kernel_params);
       }
     }
   }
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 3ecc9a0..a5ed40b 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -37,9 +37,11 @@
 #include <string>
 #include <unordered_map>
 #include <vector>
+#include <memory>
 
 #include "hw_interface.h"
 #include "hw_scale_drm.h"
+#include "hw_color_manager_drm.h"
 
 #define IOCTL_LOGE(ioctl, type) \
   DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, type, errno, strerror(errno))
@@ -179,6 +181,8 @@
   uint32_t current_mode_index_ = 0;
   sde_drm::DRMConnectorInfo connector_info_ = {};
   bool first_cycle_ = true;
+  int64_t release_fence_ = -1;
+  int64_t retire_fence_ = -1;
 
  private:
   bool synchronous_commit_ = false;
@@ -188,6 +192,7 @@
   bool resolution_switch_enabled_ = false;
   uint32_t vrefresh_ = 0;
   bool autorefresh_ = false;
+  std::unique_ptr<HWColorManagerDrm> hw_color_mgr_ = {};
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index cce2cec..73a28a8 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -483,7 +483,7 @@
     left_pipe->src_roi = src_rect;
     left_pipe->dst_roi = dst_rect;
     left_pipe->valid = true;
-    right_pipe->Reset();
+    *right_pipe = {};
   }
 
   return kErrorNone;
@@ -520,8 +520,8 @@
   }
 
   // Reset left_pipe and right_pipe to invalid by default
-  left_pipe->Reset();
-  right_pipe->Reset();
+  *left_pipe = {};
+  *right_pipe = {};
 
   if (crop_left_valid) {
     // assign left pipe