sdm: drm: Add pa sixzone feature support

Add dspp pa sixzone feature support to hw_color_mgr for drm.

Change-Id: Ib2f04aeb8c10724a1bcb38e836c24938a16c6cc7
diff --git a/sdm/libs/core/drm/hw_color_manager_drm.cpp b/sdm/libs/core/drm/hw_color_manager_drm.cpp
index b40a3b0..fd9d66f 100644
--- a/sdm/libs/core/drm/hw_color_manager_drm.cpp
+++ b/sdm/libs/core/drm/hw_color_manager_drm.cpp
@@ -48,6 +48,14 @@
 static const uint32_t kPAValMask = (1 << 14);
 static const uint32_t kPAContrastMask = (1 << 15);
 #endif
+
+#ifdef DRM_MSM_SIXZONE
+static const uint32_t kSixZoneP0Mask = 0x0FFF;
+static const uint32_t kSixZoneP1Mask = 0x0FFF0FFF;
+static const uint32_t kSixZoneHueMask = (1 << 16);
+static const uint32_t kSixZoneSatMask = (1 << 17);
+static const uint32_t kSixZoneValMask = (1 << 18);
+#endif
 #endif
 
 namespace sdm {
@@ -442,7 +450,83 @@
 
 DisplayError HWColorManagerDrm::GetDrmPASixZone(const PPFeatureInfo &in_data,
                                                 DRMPPFeatureInfo *out_data) {
-  return kErrorNotSupported;
+  DisplayError ret = kErrorNone;
+#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;
+  out_data->payload = NULL;
+
+  if (in_data.enable_flags_ & kOpsDisable) {
+    /* Complete PA features disable case */
+    return ret;
+  } else if (!(in_data.enable_flags_ & kOpsEnable)) {
+    DLOGE("Invalid ops for six zone");
+    return kErrorParameters;
+  }
+
+  if (!(sde_pa->mode & (kSixZoneHueMask | kSixZoneSatMask |
+                        kSixZoneValMask))) {
+    /* PA SixZone feature disable case, but other PA features active */
+    return ret;
+  }
+
+  if (in_data.enable_flags_ & kPaSixZoneEnable) {
+    struct drm_msm_sixzone *mdp_sixzone = NULL;
+
+    if ((!sde_pa->six_zone_curve_p0 || !sde_pa->six_zone_curve_p1) ||
+        (sde_pa->six_zone_len != SIXZONE_LUT_SIZE)) {
+        DLOGE("Invaid sixzone curve");
+        return kErrorParameters;
+    }
+
+    mdp_sixzone = new drm_msm_sixzone();
+    if (!mdp_sixzone) {
+      DLOGE("Failed to allocate memory for six zone");
+      return kErrorMemory;
+    }
+
+    mdp_sixzone->flags = 0;
+
+    if (sde_pa->mode & kSixZoneHueMask) {
+      mdp_sixzone->flags |= SIXZONE_HUE_ENABLE;
+    }
+    if (sde_pa->mode & kSixZoneSatMask) {
+      mdp_sixzone->flags |= SIXZONE_SAT_ENABLE;
+    }
+    if (sde_pa->mode & kSixZoneValMask) {
+      mdp_sixzone->flags |= SIXZONE_VAL_ENABLE;
+    }
+
+    mdp_sixzone->threshold = sde_pa->six_zone_thresh;
+    mdp_sixzone->adjust_p0 = sde_pa->six_zone_adj_p0;
+    mdp_sixzone->adjust_p1 = sde_pa->six_zone_adj_p1;
+    mdp_sixzone->sat_hold = sde_pa->six_zone_sat_hold;
+    mdp_sixzone->val_hold = sde_pa->six_zone_val_hold;
+
+    for (int i = 0; i < SIXZONE_LUT_SIZE; i++) {
+      mdp_sixzone->curve[i].p0 = sde_pa->six_zone_curve_p0[i] & kSixZoneP0Mask;
+      mdp_sixzone->curve[i].p1 = sde_pa->six_zone_curve_p1[i] & kSixZoneP1Mask;
+    }
+    out_data->payload = mdp_sixzone;
+    out_data->payload_size = sizeof(struct drm_msm_sixzone);
+  } else {
+    /* PA SixZone configuration unchanged, no better return code available */
+    ret = kErrorPermission;
+  }
+
+#endif
+  return ret;
 }
 
 DisplayError HWColorManagerDrm::GetDrmPAMemColor(const PPFeatureInfo &in_data,