display: Move sde-drm to open source

- Update make file to compile sde-drm files.
- Update copyright and year of sde-drm files.

Change-Id: I8f3b60e79b0e8680e63bf4a076b43a30c5daf68b
CRs-Fixed: 2366253
diff --git a/sde-drm/drm_plane.cpp b/sde-drm/drm_plane.cpp
new file mode 100644
index 0000000..033aced
--- /dev/null
+++ b/sde-drm/drm_plane.cpp
@@ -0,0 +1,987 @@
+/*
+* Copyright (c) 2019, 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 <stdint.h>
+#include <stdlib.h>
+#include <drm.h>
+// The 3 headers above are a workaround to prevent kernel drm.h from being used that has the
+// "virtual" keyword used for a variable. In future replace libdrm version drm.h with kernel
+// version drm/drm.h
+#include <drm_logger.h>
+#include <drm/drm_fourcc.h>
+#include <drm/sde_drm.h>
+
+#include <cstring>
+#include <map>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "drm_utils.h"
+#include "drm_plane.h"
+#include "drm_property.h"
+
+namespace sde_drm {
+
+using std::map;
+using std::string;
+using std::map;
+using std::pair;
+using std::vector;
+using std::unique_ptr;
+using std::tuple;
+using std::stringstream;
+
+static struct sde_drm_csc_v1 csc_10bit_convert[kCscTypeMax] = {
+  [kCscYuv2Rgb601L] = {
+    {
+      0x12A000000, 0x000000000,  0x198800000,
+      0x12A000000, 0x7F9B800000, 0x7F30000000,
+      0x12A000000, 0x204800000,  0x000000000,
+    },
+    { 0xffc0, 0xfe00, 0xfe00,},
+    { 0x0, 0x0, 0x0,},
+    { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
+    { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+  },
+  [kCscYuv2Rgb601FR] = {
+    {
+      0x100000000, 0x0, 0x167000000,
+      0x100000000, 0x7fa8000000, 0x7f49000000,
+      0x100000000, 0x1c5800000, 0x0,
+    },
+    { 0x0000, 0xfe00, 0xfe00,},
+    { 0x0, 0x0, 0x0,},
+    { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+    { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+  },
+  [kCscYuv2Rgb709L] = {
+    {
+      0x12a000000, 0x0, 0x1cb000000,
+      0x12a000000, 0x7fc9800000, 0x7f77800000,
+      0x12a000000, 0x21d000000, 0x0,
+    },
+    { 0xffc0, 0xfe00, 0xfe00,},
+    { 0x0, 0x0, 0x0,},
+    { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
+    { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+  },
+  [kCscYuv2Rgb2020L] = {
+    {
+      0x12b000000, 0x0, 0x1af000000,
+      0x12b000000, 0x7fd0000000, 0x7f59000000,
+      0x12b000000, 0x226000000, 0x0,
+    },
+    { 0xffc0, 0xfe00, 0xfe00,},
+    { 0x0, 0x0, 0x0,},
+    { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
+    { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+  },
+  [kCscYuv2Rgb2020FR] = {
+    {
+      0x100000000, 0x0, 0x179800000,
+      0x100000000, 0x7fd6000000, 0x7f6d800000,
+      0x100000000, 0x1e1800000, 0x0,
+    },
+    { 0x0000, 0xfe00, 0xfe00,},
+    { 0x0, 0x0, 0x0,},
+    { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+    { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+  },
+};
+
+static uint8_t REFLECT_X = 0;
+static uint8_t REFLECT_Y = 0;
+static uint8_t ROTATE_90 = 0;
+static uint8_t ROTATE_0 = 0;
+
+// FB Secure Modes
+static uint8_t NON_SECURE = 0;
+static uint8_t SECURE = 1;
+static uint8_t NON_SECURE_DIR_TRANSLATION = 2;
+static uint8_t SECURE_DIR_TRANSLATION = 3;
+
+// Multi rect modes
+static uint8_t MULTIRECT_NONE = 0;
+static uint8_t MULTIRECT_PARALLEL = 1;
+static uint8_t MULTIRECT_SERIAL = 2;
+
+static void SetRect(DRMRect &source, drm_clip_rect *target) {
+  target->x1 = uint16_t(source.left);
+  target->y1 = uint16_t(source.top);
+  target->x2 = uint16_t(source.right);
+  target->y2 = uint16_t(source.bottom);
+}
+
+static void PopulateReflect(drmModePropertyRes *prop) {
+  if (REFLECT_X) {
+    return;
+  }
+
+  if (!drm_property_type_is(prop, DRM_MODE_PROP_BITMASK)) {
+    return;
+  }
+
+  for (auto i = 0; i < prop->count_enums; i++) {
+    string enum_name(prop->enums[i].name);
+    if (enum_name == "reflect-x") {
+      REFLECT_X = prop->enums[i].value;
+    } else if (enum_name == "reflect-y") {
+      REFLECT_Y = prop->enums[i].value;
+    } else if (enum_name == "rotate-90") {
+      ROTATE_90 = prop->enums[i].value;
+    } else if (enum_name == "rotate-0") {
+      ROTATE_0 = prop->enums[i].value;
+    }
+  }
+}
+
+static void PopulateSecureModes(drmModePropertyRes *prop) {
+  static bool secure_modes_populated = false;
+  if (!secure_modes_populated) {
+    for (auto i = 0; i < prop->count_enums; i++) {
+      string enum_name(prop->enums[i].name);
+      if (enum_name == "non_sec") {
+        NON_SECURE = prop->enums[i].value;
+      } else if (enum_name == "sec") {
+        SECURE = prop->enums[i].value;
+      } else if (enum_name == "non_sec_direct_translation") {
+        NON_SECURE_DIR_TRANSLATION = prop->enums[i].value;
+      } else if (enum_name == "sec_direct_translation") {
+        SECURE_DIR_TRANSLATION = prop->enums[i].value;
+      }
+    }
+    secure_modes_populated = true;
+  }
+}
+
+static InlineRotationVersion PopulateInlineRotationVersion(uint32_t ver) {
+  switch (ver) {
+    case 0x0000: return InlineRotationVersion::kInlineRotationNone;
+    case 0x0001: return InlineRotationVersion::kInlineRotationV1;
+    default: return InlineRotationVersion::kInlineRotationNone;
+  }
+}
+
+static QSEEDStepVersion PopulateQseedStepVersion(uint32_t hw_ver) {
+  switch (hw_ver) {
+    case 0x1003: return QSEEDStepVersion::V3;
+    case 0x1004: return QSEEDStepVersion::V4;
+    case 0x2004: return QSEEDStepVersion::V3LITE_V4;
+    case 0x3000: return QSEEDStepVersion::V3LITE_V5;
+    // default value. also corresponds to (hw_ver == 0x1002)
+    default: return QSEEDStepVersion::V2;
+  }
+}
+
+static void PopulateMultiRectModes(drmModePropertyRes *prop) {
+  static bool multirect_modes_populated = false;
+  if (!multirect_modes_populated) {
+    for (auto i = 0; i < prop->count_enums; i++) {
+      string enum_name(prop->enums[i].name);
+      if (enum_name == "none") {
+        MULTIRECT_NONE = prop->enums[i].value;
+      } else if (enum_name == "parallel") {
+        MULTIRECT_PARALLEL = prop->enums[i].value;
+      } else if (enum_name == "serial") {
+        MULTIRECT_SERIAL = prop->enums[i].value;
+      }
+    }
+    multirect_modes_populated = true;
+  }
+}
+
+#define __CLASS__ "DRMPlaneManager"
+
+DRMPlaneManager::DRMPlaneManager(int fd) : fd_(fd) {}
+
+void DRMPlaneManager::Init() {
+  drmModePlaneRes *resource = drmModeGetPlaneResources(fd_);
+  if (!resource) {
+    return;
+  }
+
+  for (uint32_t i = 0; i < resource->count_planes; i++) {
+    // The enumeration order itself is the priority from high to low
+    unique_ptr<DRMPlane> plane(new DRMPlane(fd_, i));
+    drmModePlane *libdrm_plane = drmModeGetPlane(fd_, resource->planes[i]);
+    if (libdrm_plane) {
+      plane->InitAndParse(libdrm_plane);
+      plane_pool_[resource->planes[i]] = std::move(plane);
+    } else {
+      DRM_LOGE("Critical error: drmModeGetPlane() failed for plane %d.", resource->planes[i]);
+    }
+  }
+
+  drmModeFreePlaneResources(resource);
+}
+
+void DRMPlaneManager::DumpByID(uint32_t id) {
+  plane_pool_.at(id)->Dump();
+}
+
+void DRMPlaneManager::Perform(DRMOps code, uint32_t obj_id, drmModeAtomicReq *req, va_list args) {
+  auto it = plane_pool_.find(obj_id);
+  if (it == plane_pool_.end()) {
+    DRM_LOGE("Invalid plane id %d", obj_id);
+    return;
+  }
+
+  if (code == DRMOps::PLANE_SET_SCALER_CONFIG) {
+    if (it->second->ConfigureScalerLUT(req, dir_lut_blob_id_, cir_lut_blob_id_,
+                                       sep_lut_blob_id_)) {
+      DRM_LOGD("Plane %d: Configuring scaler LUTs", obj_id);
+    }
+  }
+
+  it->second->Perform(code, req, args);
+}
+
+void DRMPlaneManager::Perform(DRMOps code, drmModeAtomicReq *req, uint32_t obj_id, ...) {
+  va_list args;
+  va_start(args, obj_id);
+  Perform(code, obj_id, req, args);
+  va_end(args);
+}
+
+void DRMPlaneManager::DumpAll() {
+  for (uint32_t i = 0; i < plane_pool_.size(); i++) {
+    plane_pool_[i]->Dump();
+  }
+}
+
+void DRMPlaneManager::GetPlanesInfo(DRMPlanesInfo *info) {
+  for (auto &plane : plane_pool_) {
+    info->push_back(std::make_pair(plane.first, plane.second->GetPlaneTypeInfo()));
+  }
+}
+
+void DRMPlaneManager::UnsetUnusedPlanes(uint32_t crtc_id, drmModeAtomicReq *req) {
+  // Unset planes that were assigned to the crtc referred to by crtc_id but are not requested
+  // in this round
+  for (auto &plane : plane_pool_) {
+    uint32_t assigned_crtc = 0;
+    uint32_t requested_crtc = 0;
+    plane.second->GetAssignedCrtc(&assigned_crtc);
+    plane.second->GetRequestedCrtc(&requested_crtc);
+    if (assigned_crtc == crtc_id && requested_crtc == 0) {
+      plane.second->Unset(req);
+    }
+  }
+}
+
+void DRMPlaneManager::RetainPlanes(uint32_t crtc_id) {
+  for (auto &plane : plane_pool_) {
+    uint32_t assigned_crtc = 0;
+    plane.second->GetAssignedCrtc(&assigned_crtc);
+    if (assigned_crtc == crtc_id) {
+      // Pretend this plane was requested by client
+      plane.second->SetRequestedCrtc(crtc_id);
+      const uint32_t plane_id = plane.first;
+      DRM_LOGD("Plane %d: Retaining on CRTC %d", plane_id, crtc_id);
+    }
+  }
+}
+
+void DRMPlaneManager::PostValidate(uint32_t crtc_id, bool success) {
+  for (auto &plane : plane_pool_) {
+    plane.second->PostValidate(crtc_id, success);
+  }
+}
+
+void DRMPlaneManager::PostCommit(uint32_t crtc_id, bool success) {
+  DRM_LOGD("crtc %d", crtc_id);
+  for (auto &plane : plane_pool_) {
+    plane.second->PostCommit(crtc_id, success);
+  }
+}
+
+void DRMPlaneManager::SetScalerLUT(const DRMScalerLUTInfo &lut_info) {
+  if (lut_info.dir_lut_size) {
+    drmModeCreatePropertyBlob(fd_, reinterpret_cast<void *>(lut_info.dir_lut),
+                              lut_info.dir_lut_size, &dir_lut_blob_id_);
+  }
+  if (lut_info.cir_lut_size) {
+    drmModeCreatePropertyBlob(fd_, reinterpret_cast<void *>(lut_info.cir_lut),
+                              lut_info.cir_lut_size, &cir_lut_blob_id_);
+  }
+  if (lut_info.sep_lut_size) {
+    drmModeCreatePropertyBlob(fd_, reinterpret_cast<void *>(lut_info.sep_lut),
+                              lut_info.sep_lut_size, &sep_lut_blob_id_);
+  }
+}
+
+void DRMPlaneManager::UnsetScalerLUT() {
+  if (dir_lut_blob_id_) {
+    drmModeDestroyPropertyBlob(fd_, dir_lut_blob_id_);
+    dir_lut_blob_id_ = 0;
+  }
+  if (cir_lut_blob_id_) {
+    drmModeDestroyPropertyBlob(fd_, cir_lut_blob_id_);
+    cir_lut_blob_id_ = 0;
+  }
+  if (sep_lut_blob_id_) {
+    drmModeDestroyPropertyBlob(fd_, sep_lut_blob_id_);
+    sep_lut_blob_id_ = 0;
+  }
+}
+
+// ==============================================================================================//
+
+#undef __CLASS__
+#define __CLASS__ "DRMPlane"
+
+DRMPlane::DRMPlane(int fd, uint32_t priority) : fd_(fd), priority_(priority) {}
+
+DRMPlane::~DRMPlane() {
+  drmModeFreePlane(drm_plane_);
+}
+
+void DRMPlane::GetTypeInfo(const PropertyMap &prop_map) {
+  uint64_t blob_id;
+  drmModePropertyRes *prop;
+  DRMPlaneTypeInfo *info = &plane_type_info_;
+  // Ideally we should check if this property type is a blob and then proceed.
+  std::tie(blob_id, prop) = prop_map.at(DRMProperty::CAPABILITIES);
+  drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(fd_, blob_id);
+  if (!blob) {
+    return;
+  }
+
+  const char *fmt_str = reinterpret_cast<const char *>(blob->data);
+  info->max_linewidth = 2560;
+  info->max_scaler_linewidth = 2560;
+  info->max_rotation_linewidth = 1088;
+  info->max_upscale = 1;
+  info->max_downscale = 1;
+  info->max_horizontal_deci = 0;
+  info->max_vertical_deci = 0;
+  info->master_plane_id = 0;
+  if (info->type == DRMPlaneType::CURSOR) {
+    info->max_linewidth = 128;
+  }
+  // TODO(user): change default to V2 once we start getting V3 via capabilities blob
+  info->qseed3_version = QSEEDStepVersion::V3;
+  info->has_excl_rect = has_excl_rect_;
+
+  // We may have multiple lines with each one dedicated for something specific
+  // like formats etc
+  stringstream stream(fmt_str);
+  string line = {};
+  string pixel_formats = "pixel_formats=";
+  string max_linewidth = "max_linewidth=";
+  string max_upscale = "max_upscale=";
+  string max_downscale = "max_downscale=";
+  string max_horizontal_deci = "max_horizontal_deci=";
+  string max_vertical_deci = "max_vertical_deci=";
+  string master_plane_id = "primary_smart_plane_id=";
+  string max_pipe_bw = "max_per_pipe_bw=";
+  string scaler_version = "scaler_step_ver=";
+  string block_sec_ui = "block_sec_ui=";
+  string true_inline_rot_rev = "true_inline_rot_rev=";
+  string inline_rot_pixel_formats = "inline_rot_pixel_formats=";
+
+  while (std::getline(stream, line)) {
+    if (line.find(inline_rot_pixel_formats) != string::npos) {
+      vector<pair<uint32_t, uint64_t>> inrot_formats_supported;
+      ParseFormats(line.erase(0, inline_rot_pixel_formats.length()), &inrot_formats_supported);
+      info->inrot_fmts_supported = std::move(inrot_formats_supported);
+    } else if (line.find(pixel_formats) != string::npos) {
+      vector<pair<uint32_t, uint64_t>> formats_supported;
+      ParseFormats(line.erase(0, pixel_formats.length()), &formats_supported);
+      info->formats_supported = std::move(formats_supported);
+    } else if (line.find(max_linewidth) != string::npos) {
+      info->max_linewidth = std::stoi(line.erase(0, max_linewidth.length()));
+    } else if (line.find(max_upscale) != string::npos) {
+      info->max_upscale = std::stoi(line.erase(0, max_upscale.length()));
+    } else if (line.find(max_downscale) != string::npos) {
+      info->max_downscale = std::stoi(line.erase(0, max_downscale.length()));
+    } else if (line.find(max_horizontal_deci) != string::npos) {
+      info->max_horizontal_deci = std::stoi(line.erase(0, max_horizontal_deci.length()));
+    } else if (line.find(max_vertical_deci) != string::npos) {
+      info->max_vertical_deci = std::stoi(line.erase(0, max_vertical_deci.length()));
+    } else if (line.find(master_plane_id) != string::npos) {
+      info->master_plane_id = std::stoi(line.erase(0, master_plane_id.length()));
+      DRM_LOGI("info->master_plane_id: detected master_plane=%d", info->master_plane_id);
+    } else if (line.find(max_pipe_bw) != string::npos) {
+      info->max_pipe_bandwidth = std::stoull(line.erase(0, max_pipe_bw.length()));
+    } else if (line.find(scaler_version) != string::npos) {
+      info->qseed3_version =
+        PopulateQseedStepVersion(std::stoi(line.erase(0, scaler_version.length())));
+    } else if (line.find(block_sec_ui) != string::npos) {
+      info->block_sec_ui = !!(std::stoi(line.erase(0, block_sec_ui.length())));
+    } else if (line.find(true_inline_rot_rev) != string::npos) {
+      info->inrot_version =
+        PopulateInlineRotationVersion(std::stoi(line.erase(0, true_inline_rot_rev.length())));
+    }
+  }
+
+  info->max_scaler_linewidth = (QSEEDStepVersion::V4 == info->qseed3_version) ? 2560 :
+                                info->max_linewidth;
+  drmModeFreePropertyBlob(blob);
+}
+
+void DRMPlane::ParseProperties() {
+  // Map of property name to current value and property info pointer
+  PropertyMap prop_map;
+  bool csc = false;
+  bool scaler = false;
+  bool cursor = false;
+  drmModeObjectProperties *props =
+      drmModeObjectGetProperties(fd_, drm_plane_->plane_id, DRM_MODE_OBJECT_PLANE);
+  if (!props || !props->props || !props->prop_values) {
+    drmModeFreeObjectProperties(props);
+    return;
+  }
+
+  for (uint32_t j = 0; j < props->count_props; j++) {
+    drmModePropertyRes *info = drmModeGetProperty(fd_, props->props[j]);
+    if (!info) {
+      continue;
+    }
+
+    string property_name(info->name);
+    DRMProperty prop_enum = prop_mgr_.GetPropertyEnum(property_name);
+    if (prop_enum == DRMProperty::INVALID) {
+      DRM_LOGD("DRMProperty %s missing from global property mapping", info->name);
+      drmModeFreeProperty(info);
+      continue;
+    }
+
+    if (prop_enum == DRMProperty::EXCL_RECT) {
+      has_excl_rect_ = true;
+    }
+    if (prop_enum == DRMProperty::ROTATION) {
+      PopulateReflect(info);
+    } else if (prop_enum == DRMProperty::FB_TRANSLATION_MODE) {
+      PopulateSecureModes(info);
+    } else if (prop_enum == DRMProperty::MULTIRECT_MODE) {
+      PopulateMultiRectModes(info);
+      plane_type_info_.multirect_prop_present = true;
+    }
+
+    prop_mgr_.SetPropertyId(prop_enum, info->prop_id);
+    prop_map[prop_enum] = std::make_tuple(props->prop_values[j], info);
+    csc = prop_enum == DRMProperty::CSC_V1 ? true : csc;
+    scaler = (prop_enum == DRMProperty::SCALER_V1 || prop_enum == DRMProperty::SCALER_V2) \
+      ? true : scaler;
+    cursor = (prop_enum == DRMProperty::TYPE && props->prop_values[j] == DRM_PLANE_TYPE_CURSOR) \
+      ? true : cursor;
+
+    // Tone mapping properties.
+    if (prop_enum == DRMProperty::INVERSE_PMA) {
+      plane_type_info_.inverse_pma = true;
+    }
+
+    if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::CSC_DMA_V1 &&
+        (uint32_t)prop_enum <= (uint32_t)DRMProperty::CSC_DMA_V1) {
+      plane_type_info_.dgm_csc_version =
+          ((uint32_t)prop_enum - (uint32_t)DRMProperty::CSC_DMA_V1 + 1);
+    }
+
+    if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::SDE_DGM_1D_LUT_IGC_V5 &&
+        (uint32_t)prop_enum <= (uint32_t)DRMProperty::SDE_DGM_1D_LUT_IGC_V5) {
+      plane_type_info_.tonemap_lut_version_map[DRMTonemapLutType::DMA_1D_IGC] =
+          ((uint32_t)prop_enum - (uint32_t)DRMProperty::SDE_DGM_1D_LUT_IGC_V5 + 5);
+    }
+    if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::SDE_DGM_1D_LUT_GC_V5 &&
+        (uint32_t)prop_enum <= (uint32_t)DRMProperty::SDE_DGM_1D_LUT_GC_V5) {
+     plane_type_info_.tonemap_lut_version_map[DRMTonemapLutType::DMA_1D_GC] =
+         ((uint32_t)prop_enum - (uint32_t)DRMProperty::SDE_DGM_1D_LUT_GC_V5 + 5);
+    }
+    if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::SDE_VIG_1D_LUT_IGC_V5 &&
+        (uint32_t)prop_enum <= (uint32_t)DRMProperty::SDE_VIG_1D_LUT_IGC_V5) {
+      plane_type_info_.tonemap_lut_version_map[DRMTonemapLutType::VIG_1D_IGC] =
+          ((uint32_t)prop_enum - (uint32_t)DRMProperty::SDE_VIG_1D_LUT_IGC_V5 + 5);
+    }
+    if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::SDE_VIG_3D_LUT_GAMUT_V5 &&
+        (uint32_t)prop_enum <= (uint32_t)DRMProperty::SDE_VIG_3D_LUT_GAMUT_V5) {
+      plane_type_info_.tonemap_lut_version_map[DRMTonemapLutType::VIG_3D_GAMUT] =
+          ((uint32_t)prop_enum - (uint32_t)DRMProperty::SDE_VIG_3D_LUT_GAMUT_V5 + 5);
+    }
+  }
+
+  DRMPlaneType type = DRMPlaneType::DMA;
+  if (csc && scaler) {
+    type = DRMPlaneType::VIG;
+  } else if (cursor) {
+    type = DRMPlaneType::CURSOR;
+  }
+
+  plane_type_info_.type = type;
+  GetTypeInfo(prop_map);
+
+  for (auto &prop : prop_map) {
+    drmModeFreeProperty(std::get<1>(prop.second));
+  }
+
+  drmModeFreeObjectProperties(props);
+}
+
+void DRMPlane::InitAndParse(drmModePlane *plane) {
+  drm_plane_ = plane;
+  ParseProperties();
+
+  unique_ptr<DRMPPManager> pp_mgr(new DRMPPManager(fd_));
+  pp_mgr_ = std::move(pp_mgr);
+  pp_mgr_->Init(prop_mgr_, DRM_MODE_OBJECT_PLANE);
+}
+
+bool DRMPlane::ConfigureScalerLUT(drmModeAtomicReq *req, uint32_t dir_lut_blob_id,
+                                  uint32_t cir_lut_blob_id, uint32_t sep_lut_blob_id) {
+  if (plane_type_info_.type != DRMPlaneType::VIG || is_lut_configured_) {
+    return false;
+  }
+
+  if (dir_lut_blob_id) {
+    AddProperty(req, drm_plane_->plane_id,
+                prop_mgr_.GetPropertyId(DRMProperty::LUT_ED),
+                dir_lut_blob_id, false /* cache */, tmp_prop_val_map_);
+  }
+  if (cir_lut_blob_id) {
+    AddProperty(req, drm_plane_->plane_id,
+                prop_mgr_.GetPropertyId(DRMProperty::LUT_CIR),
+                cir_lut_blob_id, false /* cache */, tmp_prop_val_map_);
+  }
+  if (sep_lut_blob_id) {
+    AddProperty(req, drm_plane_->plane_id,
+                prop_mgr_.GetPropertyId(DRMProperty::LUT_SEP),
+                sep_lut_blob_id, false /* cache */, tmp_prop_val_map_);
+  }
+
+  return true;
+}
+
+void DRMPlane::SetExclRect(drmModeAtomicReq *req, DRMRect rect) {
+  auto prop_id = prop_mgr_.GetPropertyId(DRMProperty::EXCL_RECT);
+  drm_clip_rect clip_rect;
+  SetRect(rect, &clip_rect);
+  excl_rect_copy_ = clip_rect;
+  AddProperty(req, drm_plane_->plane_id, prop_id, reinterpret_cast<uint64_t>
+              (&excl_rect_copy_), false /* cache */, tmp_prop_val_map_);
+  DRM_LOGD("Plane %d: Setting exclusion rect [x,y,w,h][%d,%d,%d,%d]", drm_plane_->plane_id,
+           clip_rect.x1, clip_rect.y1, (clip_rect.x2 - clip_rect.x1),
+           (clip_rect.y2 - clip_rect.y1));
+}
+
+bool DRMPlane::SetCscConfig(drmModeAtomicReq *req, DRMCscType csc_type) {
+  if (plane_type_info_.type != DRMPlaneType::VIG) {
+    return false;
+  }
+
+  if (csc_type > kCscTypeMax) {
+    return false;
+  }
+
+  if (!prop_mgr_.IsPropertyAvailable(DRMProperty::CSC_V1)) {
+    return false;
+  }
+
+  auto prop_id = prop_mgr_.GetPropertyId(DRMProperty::CSC_V1);
+  if (csc_type == kCscTypeMax) {
+    AddProperty(req, drm_plane_->plane_id, prop_id, 0, false /* cache */, tmp_prop_val_map_);
+  } else {
+    csc_config_copy_ = csc_10bit_convert[csc_type];
+    AddProperty(req, drm_plane_->plane_id, prop_id,
+                reinterpret_cast<uint64_t>(&csc_config_copy_), false /* cache */,
+                tmp_prop_val_map_);
+  }
+
+  return true;
+}
+
+bool DRMPlane::SetScalerConfig(drmModeAtomicReq *req, uint64_t handle) {
+  if (plane_type_info_.type != DRMPlaneType::VIG) {
+    return false;
+  }
+
+  if (prop_mgr_.IsPropertyAvailable(DRMProperty::SCALER_V2)) {
+    auto prop_id = prop_mgr_.GetPropertyId(DRMProperty::SCALER_V2);
+    sde_drm_scaler_v2 *scaler_v2_config = reinterpret_cast<sde_drm_scaler_v2 *>(handle);
+    uint64_t scaler_data = 0;
+    // The address needs to be valid even after async commit, since we are sending address to
+    // driver directly, instead of blob. So we need to copy over contents that client sent. Client
+    // may have sent an address of object on stack which will be released after this call.
+    scaler_v2_config_copy_ = *scaler_v2_config;
+    if (scaler_v2_config_copy_.enable) {
+      scaler_data = reinterpret_cast<uint64_t>(&scaler_v2_config_copy_);
+    }
+    AddProperty(req, drm_plane_->plane_id, prop_id, scaler_data, false /* cache */,
+                tmp_prop_val_map_);
+    return true;
+  }
+
+  return false;
+}
+
+void DRMPlane::SetDecimation(drmModeAtomicReq *req, uint32_t prop_id, uint32_t prop_value) {
+  if (plane_type_info_.type == DRMPlaneType::DMA || plane_type_info_.master_plane_id) {
+    // if value is 0, client is just trying to clear previous decimation, so bail out silently
+    if (prop_value > 0) {
+      DRM_LOGE("Plane %d: Setting decimation %d is not supported.", drm_plane_->plane_id,
+               prop_value);
+    }
+    return;
+  }
+
+  // TODO(user): Currently a ViG plane in smart DMA mode could receive a non-zero decimation value
+  // but there is no good way to catch. In any case fix will be in client
+  AddProperty(req, drm_plane_->plane_id, prop_id, prop_value, true /* cache */, tmp_prop_val_map_);
+  DRM_LOGD("Plane %d: Setting decimation %d", drm_plane_->plane_id, prop_value);
+}
+
+void DRMPlane::PostValidate(uint32_t crtc_id, bool /*success*/) {
+  if (requested_crtc_id_ == crtc_id) {
+    SetRequestedCrtc(0);
+    tmp_prop_val_map_ = committed_prop_val_map_;
+  }
+}
+
+void DRMPlane::PostCommit(uint32_t crtc_id, bool success) {
+  DRM_LOGD("crtc %d", crtc_id);
+  if (!success) {
+    // To reset
+    PostValidate(crtc_id, success);
+    return;
+  }
+
+  uint32_t assigned_crtc = 0;
+  uint32_t requested_crtc = 0;
+
+  GetAssignedCrtc(&assigned_crtc);
+  GetRequestedCrtc(&requested_crtc);
+
+  // In future, it is possible that plane is already attached in case of continuous splash. This
+  // will cause the first commit to only unstage pipes. We want to mark luts as configured only
+  // when they really are, which typically happens if a crtc is requested for a plane
+  if (requested_crtc == crtc_id && !is_lut_configured_) {
+    is_lut_configured_ = true;
+  }
+
+  if (requested_crtc && assigned_crtc && requested_crtc != assigned_crtc) {
+    // We should never be here
+    DRM_LOGE("Found plane %d switching from crtc %d to crtc %d", drm_plane_->plane_id,
+             assigned_crtc, requested_crtc);
+  }
+
+  // If we have set a pipe OR unset a pipe during commit, update states
+  if (requested_crtc == crtc_id || assigned_crtc == crtc_id) {
+    committed_prop_val_map_ = tmp_prop_val_map_;
+    SetAssignedCrtc(requested_crtc);
+    SetRequestedCrtc(0);
+  }
+}
+
+void DRMPlane::Perform(DRMOps code, drmModeAtomicReq *req, va_list args) {
+  uint32_t prop_id = 0;
+  uint32_t obj_id = drm_plane_->plane_id;
+
+  switch (code) {
+    // TODO(user): Check if these exist in map before attempting to access
+    case DRMOps::PLANE_SET_SRC_RECT: {
+      DRMRect rect = va_arg(args, DRMRect);
+      // source co-ordinates accepted by DRM are 16.16 fixed point
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::SRC_X);
+      AddProperty(req, obj_id, prop_id, rect.left << 16, true /* cache */, tmp_prop_val_map_);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::SRC_Y);
+      AddProperty(req, obj_id, prop_id, rect.top << 16, true /* cache */, tmp_prop_val_map_);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::SRC_W);
+      AddProperty(req, obj_id, prop_id, (rect.right - rect.left) << 16, true /* cache */,
+                  tmp_prop_val_map_);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::SRC_H);
+      AddProperty(req, obj_id, prop_id, (rect.bottom - rect.top) << 16, true /* cache */,
+                  tmp_prop_val_map_);
+      DRM_LOGV("Plane %d: Setting crop [x,y,w,h][%d,%d,%d,%d]", obj_id, rect.left,
+               rect.top, (rect.right - rect.left), (rect.bottom - rect.top));
+    } break;
+
+    case DRMOps::PLANE_SET_DST_RECT: {
+      DRMRect rect = va_arg(args, DRMRect);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::CRTC_X);
+      AddProperty(req, obj_id, prop_id, rect.left, true /* cache */, tmp_prop_val_map_);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::CRTC_Y);
+      AddProperty(req, obj_id, prop_id, rect.top, true /* cache */, tmp_prop_val_map_);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::CRTC_W);
+      AddProperty(req, obj_id, prop_id, (rect.right - rect.left), true /* cache */,
+                  tmp_prop_val_map_);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::CRTC_H);
+      AddProperty(req, obj_id, prop_id, (rect.bottom - rect.top), true /* cache */,
+                  tmp_prop_val_map_);
+      DRM_LOGV("Plane %d: Setting dst [x,y,w,h][%d,%d,%d,%d]", obj_id, rect.left,
+               rect.top, (rect.right - rect.left), (rect.bottom - rect.top));
+    } break;
+    case DRMOps::PLANE_SET_EXCL_RECT: {
+      DRMRect excl_rect = va_arg(args, DRMRect);
+      SetExclRect(req, excl_rect);
+    } break;
+
+    case DRMOps::PLANE_SET_ZORDER: {
+      uint32_t zpos = va_arg(args, uint32_t);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::ZPOS);
+      AddProperty(req, obj_id, prop_id, zpos, true /* cache */, tmp_prop_val_map_);
+      DRM_LOGD("Plane %d: Setting z %d", obj_id, zpos);
+    } break;
+
+    case DRMOps::PLANE_SET_ROTATION: {
+      uint32_t rot_bit_mask = va_arg(args, uint32_t);
+      uint32_t drm_rot_bit_mask = 0;
+      if (rot_bit_mask & static_cast<uint32_t>(DRMRotation::FLIP_H)) {
+        drm_rot_bit_mask |= 1 << REFLECT_X;
+      }
+      if (rot_bit_mask & static_cast<uint32_t>(DRMRotation::FLIP_V)) {
+        drm_rot_bit_mask |= 1 << REFLECT_Y;
+      }
+      if (rot_bit_mask & static_cast<uint32_t>(DRMRotation::ROT_90)) {
+        drm_rot_bit_mask |= 1 << ROTATE_90;
+      } else {
+        drm_rot_bit_mask |= 1 << ROTATE_0;
+      }
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::ROTATION);
+      AddProperty(req, obj_id, prop_id, drm_rot_bit_mask, true /* cache */, tmp_prop_val_map_);
+      DRM_LOGV("Plane %d: Setting rotation mask %x", obj_id, drm_rot_bit_mask);
+    } break;
+
+    case DRMOps::PLANE_SET_ALPHA: {
+      uint32_t alpha = va_arg(args, uint32_t);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::ALPHA);
+      AddProperty(req, obj_id, prop_id, alpha, true /* cache */, tmp_prop_val_map_);
+      DRM_LOGV("Plane %d: Setting alpha %d", obj_id, alpha);
+    } break;
+
+    case DRMOps::PLANE_SET_BLEND_TYPE: {
+      uint32_t blending = va_arg(args, uint32_t);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::BLEND_OP);
+      AddProperty(req, obj_id, prop_id, blending, true /* cache */, tmp_prop_val_map_);
+      DRM_LOGV("Plane %d: Setting blending %d", obj_id, blending);
+    } break;
+
+    case DRMOps::PLANE_SET_H_DECIMATION: {
+      uint32_t deci = va_arg(args, uint32_t);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::H_DECIMATE);
+      SetDecimation(req, prop_id, deci);
+    } break;
+
+    case DRMOps::PLANE_SET_V_DECIMATION: {
+      uint32_t deci = va_arg(args, uint32_t);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::V_DECIMATE);
+      SetDecimation(req, prop_id, deci);
+    } break;
+
+    case DRMOps::PLANE_SET_SRC_CONFIG: {
+      bool src_config = va_arg(args, uint32_t);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::SRC_CONFIG);
+      AddProperty(req, obj_id, prop_id, src_config, true /* cache */, tmp_prop_val_map_);
+      DRM_LOGV("Plane %d: Setting src_config flags-%x", obj_id, src_config);
+    } break;
+
+    case DRMOps::PLANE_SET_CRTC: {
+      uint32_t crtc_id = va_arg(args, uint32_t);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::CRTC_ID);
+      AddProperty(req, obj_id, prop_id, crtc_id, true /* cache */, tmp_prop_val_map_);
+      SetRequestedCrtc(crtc_id);
+      DRM_LOGV("Plane %d: Setting crtc %d", obj_id, crtc_id);
+    } break;
+
+    case DRMOps::PLANE_SET_FB_ID: {
+      uint32_t fb_id = va_arg(args, uint32_t);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::FB_ID);
+      AddProperty(req, obj_id, prop_id, fb_id, true /* cache */, tmp_prop_val_map_);
+      DRM_LOGV("Plane %d: Setting fb_id %d", obj_id, fb_id);
+    } break;
+
+    case DRMOps::PLANE_SET_ROT_FB_ID: {
+      uint32_t fb_id = va_arg(args, uint32_t);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::ROT_FB_ID);
+      drmModeAtomicAddProperty(req, obj_id, prop_id, fb_id);
+      DRM_LOGV("Plane %d: Setting rot_fb_id %d", obj_id, fb_id);
+    } break;
+
+    case DRMOps::PLANE_SET_INPUT_FENCE: {
+      int fence = va_arg(args, int);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::INPUT_FENCE);
+      AddProperty(req, obj_id, prop_id, fence, false /* cache */, tmp_prop_val_map_);
+      DRM_LOGV("Plane %d: Setting input fence %d", obj_id, fence);
+    } break;
+
+    case DRMOps::PLANE_SET_SCALER_CONFIG: {
+      uint64_t handle = va_arg(args, uint64_t);
+      if (SetScalerConfig(req, handle)) {
+        DRM_LOGV("Plane %d: Setting scaler config", obj_id);
+      }
+    } break;
+
+    case DRMOps::PLANE_SET_FB_SECURE_MODE: {
+      int secure_mode = va_arg(args, int);
+      uint32_t fb_secure_mode = NON_SECURE;
+      switch (secure_mode) {
+        case (int)DRMSecureMode::NON_SECURE:
+          fb_secure_mode = NON_SECURE;
+          break;
+        case (int)DRMSecureMode::SECURE:
+          fb_secure_mode = SECURE;
+          break;
+        case (int)DRMSecureMode::NON_SECURE_DIR_TRANSLATION:
+          fb_secure_mode = NON_SECURE_DIR_TRANSLATION;
+          break;
+        case (int)DRMSecureMode::SECURE_DIR_TRANSLATION:
+          fb_secure_mode = SECURE_DIR_TRANSLATION;
+          break;
+        default:
+          DRM_LOGE("Invalid secure mode %d to set on plane %d", secure_mode, obj_id);
+          break;
+      }
+
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::FB_TRANSLATION_MODE);
+      AddProperty(req, obj_id, prop_id, fb_secure_mode, true /* cache */, tmp_prop_val_map_);
+      DRM_LOGD("Plane %d: Setting FB secure mode %d", obj_id, fb_secure_mode);
+    } break;
+
+    case DRMOps::PLANE_SET_CSC_CONFIG: {
+      uint32_t* csc_type = va_arg(args, uint32_t*);
+      if (csc_type) {
+        SetCscConfig(req, (DRMCscType)*csc_type);
+      }
+    } break;
+
+    case DRMOps::PLANE_SET_MULTIRECT_MODE: {
+      DRMMultiRectMode drm_multirect_mode = (DRMMultiRectMode)va_arg(args, uint32_t);
+      SetMultiRectMode(req, drm_multirect_mode);
+    } break;
+
+    case DRMOps::PLANE_SET_INVERSE_PMA: {
+       uint32_t pma = va_arg(args, uint32_t);
+       prop_id = prop_mgr_.GetPropertyId(DRMProperty::INVERSE_PMA);
+       AddProperty(req, obj_id, prop_id, pma, true /* cache */, tmp_prop_val_map_);
+       DRM_LOGD("Plane %d: %s inverse pma", obj_id, pma ? "Setting" : "Resetting");
+     } break;
+
+    case DRMOps::PLANE_SET_DGM_CSC_CONFIG: {
+      uint64_t handle = va_arg(args, uint64_t);
+      if (SetDgmCscConfig(req, handle)) {
+        DRM_LOGD("Plane %d: Setting Csc Lut config", obj_id);
+      }
+    } break;
+
+    case DRMOps::PLANE_SET_POST_PROC: {
+       DRMPPFeatureInfo *data = va_arg(args, DRMPPFeatureInfo*);
+       if (data) {
+         DRM_LOGD("Plane %d: Set post proc", obj_id);
+         pp_mgr_->SetPPFeature(req, obj_id, *data);
+       }
+     } break;
+
+    default:
+      DRM_LOGE("Invalid opcode %d for DRM Plane %d", code, obj_id);
+  }
+}
+
+void DRMPlane::PerformWrapper(DRMOps code, drmModeAtomicReq *req, ...) {
+  va_list args;
+  va_start(args, req);
+  Perform(code, req, args);
+  va_end(args);
+}
+
+void DRMPlane::Dump() {
+  DRM_LOGE(
+      "id: %d\tcrtc id: %d\tfb id: %d\tCRTC_xy: %dx%d\txy: %dx%d\tgamma "
+      "size: %d\tpossible crtc: 0x%x\n",
+      drm_plane_->plane_id, drm_plane_->crtc_id, drm_plane_->fb_id, drm_plane_->crtc_x,
+      drm_plane_->crtc_y, drm_plane_->x, drm_plane_->y, drm_plane_->gamma_size,
+      drm_plane_->possible_crtcs);
+  DRM_LOGE("Format Suported: \n");
+  for (uint32_t i = 0; i < (uint32_t)drm_plane_->count_formats; i++)
+    DRM_LOGE(" %4.4s", (char *)&drm_plane_->formats[i]);
+}
+
+void DRMPlane::SetMultiRectMode(drmModeAtomicReq *req, DRMMultiRectMode drm_multirect_mode) {
+    if (!plane_type_info_.multirect_prop_present) {
+      return;
+    }
+    uint32_t obj_id = drm_plane_->plane_id;
+    uint32_t multirect_mode = MULTIRECT_NONE;
+    switch (drm_multirect_mode) {
+      case DRMMultiRectMode::NONE:
+        multirect_mode = MULTIRECT_NONE;
+        break;
+      case DRMMultiRectMode::PARALLEL:
+        multirect_mode = MULTIRECT_PARALLEL;
+        break;
+      case DRMMultiRectMode::SERIAL:
+        multirect_mode = MULTIRECT_SERIAL;
+        break;
+      default:
+        DRM_LOGE("Invalid multirect mode %d to set on plane %d", drm_multirect_mode, obj_id);
+        break;
+    }
+    auto prop_id = prop_mgr_.GetPropertyId(DRMProperty::MULTIRECT_MODE);
+    AddProperty(req, obj_id, prop_id, multirect_mode, true /* cache */, tmp_prop_val_map_);
+    DRM_LOGD("Plane %d: Setting multirect_mode %d", obj_id, multirect_mode);
+}
+
+void DRMPlane::Unset(drmModeAtomicReq *req) {
+  DRM_LOGD("Plane %d: Unsetting from crtc %d", drm_plane_->plane_id, assigned_crtc_id_);
+  PerformWrapper(DRMOps::PLANE_SET_FB_ID, req, 0);
+  PerformWrapper(DRMOps::PLANE_SET_CRTC, req, 0);
+  DRMRect rect = {0, 0, 0, 0};
+  PerformWrapper(DRMOps::PLANE_SET_SRC_RECT, req, rect);
+  PerformWrapper(DRMOps::PLANE_SET_DST_RECT, req, rect);
+  PerformWrapper(DRMOps::PLANE_SET_EXCL_RECT, req, rect);
+  if (plane_type_info_.inverse_pma) {
+    PerformWrapper(DRMOps::PLANE_SET_INVERSE_PMA, req, 0);
+  }
+  tmp_prop_val_map_.clear();
+  committed_prop_val_map_.clear();
+}
+
+bool DRMPlane::SetDgmCscConfig(drmModeAtomicReq *req, uint64_t handle) {
+  if (plane_type_info_.type == DRMPlaneType::DMA &&
+      prop_mgr_.IsPropertyAvailable(DRMProperty::CSC_DMA_V1)) {
+    auto prop_id = prop_mgr_.GetPropertyId(DRMProperty::CSC_DMA_V1);
+    sde_drm_csc_v1 *csc_v1 = reinterpret_cast<sde_drm_csc_v1 *>(handle);
+    uint64_t csc_v1_data = 0;
+    sde_drm_csc_v1 csc_v1_tmp = {};
+    csc_config_copy_ = *csc_v1;
+    if (std::memcmp(&csc_config_copy_, &csc_v1_tmp, sizeof(sde_drm_csc_v1)) != 0) {
+      csc_v1_data = reinterpret_cast<uint64_t>(&csc_config_copy_);
+    }
+    DRM_LOGV("Dgm CSC = %d", csc_v1_data);
+    AddProperty(req, drm_plane_->plane_id, prop_id,
+                reinterpret_cast<uint64_t>(csc_v1_data), false /* cache */,
+                tmp_prop_val_map_);
+
+    return true;
+  }
+
+  return false;
+}
+
+}  // namespace sde_drm