sdm: Add support for compliance test mode for DP

1. Add functionality in qdutils to get the DP test config from the
   sysfs node.
2. Add support to generate ColorRamp, ColorSquare and Black and White
   vertical line test pattern for 18/24/30 bpp DP display
3. Create layer stack with test layer and ignore all layers from the
   SF framework.
4. Generate the pattern with 18/24/30 bpp based on pattern type and
   bpp read from sysfs node and send it to DP interface.
5. Add support to calculate CRC to validate the color pattern.

Change-Id: I49469d94a96ada729d24d7cc03a7e79f2af6edc0
CRs-Fixed: 1107663
diff --git a/libqdutils/qd_utils.cpp b/libqdutils/qd_utils.cpp
index 43fb715..b84ae87 100644
--- a/libqdutils/qd_utils.cpp
+++ b/libqdutils/qd_utils.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -31,7 +31,7 @@
 
 namespace qdutils {
 
-int parseLine(char *input, char *tokens[], const uint32_t maxToken, uint32_t *count) {
+static int parseLine(char *input, char *tokens[], const uint32_t maxToken, uint32_t *count) {
     char *tmpToken = NULL;
     char *tmpPtr;
     uint32_t index = 0;
@@ -49,6 +49,38 @@
     return 0;
 }
 
+static int getExternalNode(const char *type) {
+    FILE *displayDeviceFP = NULL;
+    char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
+    char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
+    int j = 0;
+
+    for(j = 0; j < HWC_NUM_DISPLAY_TYPES; j++) {
+        snprintf (msmFbTypePath, sizeof(msmFbTypePath),
+                  "/sys/class/graphics/fb%d/msm_fb_type", j);
+        displayDeviceFP = fopen(msmFbTypePath, "r");
+        if(displayDeviceFP) {
+            fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
+                    displayDeviceFP);
+            if(strncmp(fbType, type, strlen(type)) == 0) {
+                ALOGD("%s: %s is at fb%d", __func__, type, j);
+                fclose(displayDeviceFP);
+                break;
+            }
+            fclose(displayDeviceFP);
+        } else {
+            ALOGE("%s: Failed to open fb node %d", __func__, j);
+        }
+    }
+
+    if (j < HWC_NUM_DISPLAY_TYPES)
+        return j;
+    else
+        ALOGE("%s: Failed to find %s node", __func__, type);
+
+    return -1;
+}
+
 int querySDEInfo(HWQueryType type, int *value) {
     FILE *fileptr = NULL;
     const char *featureName;
@@ -102,37 +134,8 @@
     return 0;
 }
 
-int getHDMINode(void)
-{
-    FILE *displayDeviceFP = NULL;
-    char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
-    char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
-    int j = 0;
-
-    for(j = 0; j < HWC_NUM_DISPLAY_TYPES; j++) {
-        snprintf (msmFbTypePath, sizeof(msmFbTypePath),
-                  "/sys/class/graphics/fb%d/msm_fb_type", j);
-        displayDeviceFP = fopen(msmFbTypePath, "r");
-        if(displayDeviceFP) {
-            fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
-                    displayDeviceFP);
-            if(strncmp(fbType, "dtv panel", strlen("dtv panel")) == 0) {
-                ALOGD("%s: HDMI is at fb%d", __func__, j);
-                fclose(displayDeviceFP);
-                break;
-            }
-            fclose(displayDeviceFP);
-        } else {
-            ALOGE("%s: Failed to open fb node %d", __func__, j);
-        }
-    }
-
-    if (j < HWC_NUM_DISPLAY_TYPES)
-        return j;
-    else
-        ALOGE("%s: Failed to find HDMI node", __func__);
-
-    return -1;
+int getHDMINode(void) {
+    return getExternalNode("dtv panel");
 }
 
 int getEdidRawData(char *buffer)
@@ -162,4 +165,80 @@
     return size;
 }
 
+bool isDPConnected() {
+    char connectPath[MAX_FRAME_BUFFER_NAME_SIZE];
+    FILE *connectFile = NULL;
+    size_t len = MAX_STRING_LENGTH;
+    char stringBuffer[MAX_STRING_LENGTH];
+    char *line = stringBuffer;
+
+    int nodeId = getExternalNode("dp panel");
+    if (nodeId < 0) {
+        ALOGE("%s no DP node found", __func__);
+        return false;
+    }
+
+    snprintf(connectPath, sizeof(connectPath),
+             "/sys/class/graphics/fb%d/connected", nodeId);
+
+    connectFile = fopen(connectPath, "rb");
+    if (!connectFile) {
+        ALOGW("Failed to open connect node for device node %d", nodeId);
+        return false;
+    }
+
+    if (getline(&line, &len, connectFile) < 0) {
+        fclose(connectFile);
+        return false;
+    }
+
+    fclose(connectFile);
+
+    return atoi(line);
+}
+
+int getDPTestConfig(uint32_t *panelBpp, uint32_t *patternType) {
+    if (!panelBpp || !patternType) {
+        return -1;
+    }
+
+    char configPath[MAX_FRAME_BUFFER_NAME_SIZE];
+    FILE *configFile = NULL;
+    uint32_t tokenCount = 0;
+    const uint32_t maxCount = 10;
+    char *tokens[maxCount] = { NULL };
+    size_t len = MAX_STRING_LENGTH;
+    char stringBuffer[MAX_STRING_LENGTH];
+    char *line = stringBuffer;
+
+    int nodeId = getExternalNode("dp panel");
+    if (nodeId < 0) {
+        ALOGE("%s no DP node found", __func__);
+        return -EINVAL;
+    }
+
+    snprintf(configPath, sizeof(configPath),
+             "/sys/class/graphics/fb%d/config", nodeId);
+
+    configFile = fopen(configPath, "rb");
+    if (!configFile) {
+        ALOGW("Failed to open config node for device node %d", nodeId);
+        return -EINVAL;
+    }
+
+    while (getline(&line, &len, configFile) != -1) {
+        if (!parseLine(line, tokens, maxCount, &tokenCount)) {
+            if (!strncmp(tokens[0], "bpp", strlen("bpp"))) {
+                *panelBpp = static_cast<uint32_t>(atoi(tokens[1]));
+            } else  if (!strncmp(tokens[0], "pattern", strlen("pattern"))) {
+                *patternType = static_cast<uint32_t>(atoi(tokens[1]));
+            }
+        }
+    }
+
+    fclose(configFile);
+
+    return 0;
+}
+
 }; //namespace qdutils