Merge "hwc: Extend pause/resume functionality to VDS displays"
diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp
index 311fd8f..bb6c2c8 100644
--- a/libgralloc/ionalloc.cpp
+++ b/libgralloc/ionalloc.cpp
@@ -28,7 +28,7 @@
  */
 
 #define DEBUG 0
-#include <linux/ioctl.h>
+#include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <stdlib.h>
 #include <fcntl.h>
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 893fee0..bfcfa78 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -212,6 +212,7 @@
             if(ctx->mCopyBit[dpy])
                 ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
         }
+        setGPUHint(ctx, list);
     }
     return 0;
 }
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 22b8baf..2d65755 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -53,6 +53,7 @@
     static bool init(hwc_context_t *ctx);
     static void resetIdleFallBack() { sIdleFallBack = false; }
     static void reset() { sHandleTimeout = false; };
+    static bool isIdleFallback() { return sIdleFallBack; }
 
 protected:
     enum { MAX_SEC_LAYERS = 1 }; //TODO add property support
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 751aef3..d9e75dc 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -52,6 +52,26 @@
 using namespace overlay::utils;
 namespace ovutils = overlay::utils;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EGLAPI EGLBoolean eglGpuPerfHintQCOM(EGLDisplay dpy, EGLContext ctx,
+                                           EGLint *attrib_list);
+#define EGL_GPU_HINT_1        0x32D0
+#define EGL_GPU_HINT_2        0x32D1
+
+#define EGL_GPU_LEVEL_0       0x0
+#define EGL_GPU_LEVEL_1       0x1
+#define EGL_GPU_LEVEL_2       0x2
+#define EGL_GPU_LEVEL_3       0x3
+#define EGL_GPU_LEVEL_4       0x4
+#define EGL_GPU_LEVEL_5       0x5
+
+#ifdef __cplusplus
+}
+#endif
+
 namespace qhwc {
 
 bool isValidResolution(hwc_context_t *ctx, uint32_t xres, uint32_t yres)
@@ -245,6 +265,15 @@
         ctx->mMDPDownscaleEnabled = true;
     }
 
+    // Initialize gpu perfomance hint related parameters
+    property_get("sys.hwc.gpu_perf_mode", value, "0");
+    ctx->mGPUHintInfo.mGpuPerfModeEnable = atoi(value)? true : false;
+
+    ctx->mGPUHintInfo.mEGLDisplay = NULL;
+    ctx->mGPUHintInfo.mEGLContext = NULL;
+    ctx->mGPUHintInfo.mPrevCompositionGLES = false;
+    ctx->mGPUHintInfo.mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
+
     ALOGI("Initializing Qualcomm Hardware Composer");
     ALOGI("MDP version: %d", ctx->mMDP.version);
 }
@@ -1981,6 +2010,78 @@
     return true;
 }
 
+bool isGLESComp(hwc_context_t *ctx,
+                     hwc_display_contents_1_t* list) {
+    int numAppLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
+    for(int index = 0; index < numAppLayers; index++) {
+        hwc_layer_1_t* layer = &(list->hwLayers[index]);
+        if(layer->compositionType == HWC_FRAMEBUFFER)
+            return true;
+    }
+    return false;
+}
+
+void setGPUHint(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
+    struct gpu_hint_info *gpuHint = &ctx->mGPUHintInfo;
+    if(!gpuHint->mGpuPerfModeEnable)
+        return;
+    /* Set the GPU hint flag to high for MIXED/GPU composition only for
+       first frame after MDP -> GPU/MIXED mode transition. Set the GPU
+       hint to default if the previous composition is GPU or current GPU
+       composition is due to idle fallback */
+    if(!gpuHint->mEGLDisplay || !gpuHint->mEGLContext) {
+        gpuHint->mEGLDisplay = eglGetCurrentDisplay();
+        if(!gpuHint->mEGLDisplay) {
+            ALOGW("%s Warning: EGL current display is NULL", __FUNCTION__);
+            return;
+        }
+        gpuHint->mEGLContext = eglGetCurrentContext();
+        if(!gpuHint->mEGLContext) {
+            ALOGW("%s Warning: EGL current context is NULL", __FUNCTION__);
+            return;
+        }
+    }
+    if(isGLESComp(ctx, list)) {
+        if(!gpuHint->mPrevCompositionGLES && !MDPComp::isIdleFallback()) {
+            EGLint attr_list[] = {EGL_GPU_HINT_1,
+                                  EGL_GPU_LEVEL_3,
+                                  EGL_NONE };
+            if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_3) &&
+                !eglGpuPerfHintQCOM(gpuHint->mEGLDisplay,
+                                    gpuHint->mEGLContext, attr_list)) {
+                ALOGW("eglGpuPerfHintQCOM failed for Built in display");
+            } else {
+                gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_3;
+                gpuHint->mPrevCompositionGLES = true;
+            }
+        } else {
+            EGLint attr_list[] = {EGL_GPU_HINT_1,
+                                  EGL_GPU_LEVEL_0,
+                                  EGL_NONE };
+            if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_0) &&
+                !eglGpuPerfHintQCOM(gpuHint->mEGLDisplay,
+                                    gpuHint->mEGLContext, attr_list)) {
+                ALOGW("eglGpuPerfHintQCOM failed for Built in display");
+            } else {
+                gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
+            }
+        }
+    } else {
+        /* set the GPU hint flag to default for MDP composition */
+        EGLint attr_list[] = {EGL_GPU_HINT_1,
+                              EGL_GPU_LEVEL_0,
+                              EGL_NONE };
+        if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_0) &&
+                !eglGpuPerfHintQCOM(gpuHint->mEGLDisplay,
+                                    gpuHint->mEGLContext, attr_list)) {
+            ALOGW("eglGpuPerfHintQCOM failed for Built in display");
+        } else {
+            gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
+        }
+        gpuHint->mPrevCompositionGLES = false;
+    }
+}
+
 void BwcPM::setBwc(const hwc_rect_t& crop,
             const hwc_rect_t& dst, const int& transform,
             ovutils::eMdpFlags& mdpFlags) {
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index b4b5232..ad023ad 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -30,6 +30,8 @@
 #include <utils/String8.h>
 #include "qdMetaData.h"
 #include <overlayUtils.h>
+#include <EGL/egl.h>
+
 
 #define ALIGN_TO(x, align)     (((x) + ((align)-1)) & ~((align)-1))
 #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
@@ -341,6 +343,12 @@
 
 bool isDisplaySplit(hwc_context_t* ctx, int dpy);
 
+// Set the GPU hint flag to high for MIXED/GPU composition only for
+// first frame after MDP to GPU/MIXED mode transition.
+// Set the GPU hint to default if the current composition type is GPU
+// due to idle fallback or MDP composition.
+void setGPUHint(hwc_context_t* ctx, hwc_display_contents_1_t* list);
+
 // Inline utility functions
 static inline bool isSkipLayer(const hwc_layer_1_t* l) {
     return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
@@ -439,6 +447,20 @@
     ANIMATION_STARTED,
 };
 
+// Structure holds the information about the GPU hint.
+struct gpu_hint_info {
+    // system level flag to enable gpu_perf_mode
+    bool mGpuPerfModeEnable;
+    // Stores the current GPU performance mode DEFAULT/HIGH
+    bool mCurrGPUPerfMode;
+    // true if previous composition used GPU
+    bool mPrevCompositionGLES;
+    // Stores the EGLContext of current process
+    EGLContext mEGLContext;
+    // Stores the EGLDisplay of current process
+    EGLDisplay mEGLDisplay;
+};
+
 // -----------------------------------------------------------------------------
 // HWC context
 // This structure contains overall state
@@ -502,6 +524,7 @@
     // Downscale feature switch, set via system the property
     // sys.hwc.mdp_downscale_enabled
     bool mMDPDownscaleEnabled;
+    struct gpu_hint_info mGPUHintInfo;
 };
 
 namespace qhwc {
diff --git a/libhwcomposer/hwc_vsync.cpp b/libhwcomposer/hwc_vsync.cpp
index 3729f21..6781e7b 100644
--- a/libhwcomposer/hwc_vsync.cpp
+++ b/libhwcomposer/hwc_vsync.cpp
@@ -37,6 +37,10 @@
 
 #define HWC_VSYNC_THREAD_NAME "hwcVsyncThread"
 #define MAX_SYSFS_FILE_PATH             255
+#define PANEL_ON_STR "panel_power_on ="
+#define ARRAY_LENGTH(array) (sizeof((array))/sizeof((array)[0]))
+const int MAX_DATA = 64;
+bool logvsync = false;
 
 int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable)
 {
@@ -51,6 +55,40 @@
     return ret;
 }
 
+static void handle_vsync_event(hwc_context_t* ctx, int dpy, char *data)
+{
+    // extract timestamp
+    uint64_t timestamp = 0;
+    if (!strncmp(data, "VSYNC=", strlen("VSYNC="))) {
+        timestamp = strtoull(data + strlen("VSYNC="), NULL, 0);
+    }
+    // send timestamp to SurfaceFlinger
+    ALOGD_IF (logvsync, "%s: timestamp %"PRIu64" sent to SF for dpy=%d",
+            __FUNCTION__, timestamp, dpy);
+    ctx->proc->vsync(ctx->proc, dpy, timestamp);
+}
+
+static void handle_blank_event(hwc_context_t* ctx, int dpy, char *data)
+{
+    if (!strncmp(data, PANEL_ON_STR, strlen(PANEL_ON_STR))) {
+        uint32_t poweron = strtoul(data + strlen(PANEL_ON_STR), NULL, 0);
+        ALOGI("%s: dpy:%d panel power state: %d", __FUNCTION__, dpy, poweron);
+        ctx->dpyAttr[dpy].isActive = poweron ? true: false;
+    }
+}
+
+struct event {
+    const char* name;
+    void (*callback)(hwc_context_t* ctx, int dpy, char *data);
+};
+
+struct event event_list[] =  {
+    { "vsync_event", handle_vsync_event },
+    { "show_blank_event", handle_blank_event },
+};
+
+#define num_events ARRAY_LENGTH(event_list)
+
 static void *vsync_loop(void *param)
 {
     hwc_context_t * ctx = reinterpret_cast<hwc_context_t *>(param);
@@ -60,14 +98,11 @@
     setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY +
                 android::PRIORITY_MORE_FAVORABLE);
 
-    const int MAX_DATA = 64;
     char vdata[MAX_DATA];
-    bool logvsync = false;
-
-    struct pollfd pfd[2];
-    int fb_fd[2];
-    uint64_t timestamp[2] = {0,0};
-    int num_displays;
+    //Number of physical displays
+    //We poll on all the nodes.
+    int num_displays = HWC_NUM_DISPLAY_TYPES - 1;
+    struct pollfd pfd[num_displays][num_events];
 
     char property[PROPERTY_VALUE_MAX];
     if(property_get("debug.hwc.fakevsync", property, NULL) > 0) {
@@ -80,69 +115,62 @@
             logvsync = true;
     }
 
-    if (ctx->mExtDisplay->isConnected())
-        num_displays = 2;
-    else
-        num_displays = 1;
+    char node_path[MAX_SYSFS_FILE_PATH];
 
-    char vsync_node_path[MAX_SYSFS_FILE_PATH];
     for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
-        snprintf(vsync_node_path, sizeof(vsync_node_path),
-                "/sys/class/graphics/fb%d/vsync_event",
-                dpy == HWC_DISPLAY_PRIMARY ? 0 :
-                overlay::Overlay::getInstance()->
-                                getFbForDpy(HWC_DISPLAY_EXTERNAL));
-        ALOGI("%s: Reading vsync for dpy=%d from %s", __FUNCTION__, dpy,
-                vsync_node_path);
-        fb_fd[dpy] = open(vsync_node_path, O_RDONLY);
+        for(size_t ev = 0; ev < num_events; ev++) {
+            snprintf(node_path, sizeof(node_path),
+                    "/sys/class/graphics/fb%d/%s",
+                    dpy == HWC_DISPLAY_PRIMARY ? 0 :
+                    overlay::Overlay::getInstance()->
+                    getFbForDpy(HWC_DISPLAY_EXTERNAL),
+                    event_list[ev].name);
 
-        if (fb_fd[dpy] < 0) {
-            // Make sure fb device is opened before starting this thread so this
-            // never happens.
-            ALOGE ("%s:not able to open vsync node for dpy=%d, %s",
-                    __FUNCTION__, dpy, strerror(errno));
-            if (dpy == HWC_DISPLAY_PRIMARY) {
-                ctx->vstate.fakevsync = true;
-                break;
+            ALOGI("%s: Reading event %zu for dpy %d from %s", __FUNCTION__,
+                    ev, dpy, node_path);
+            pfd[dpy][ev].fd = open(node_path, O_RDONLY);
+
+            if (dpy == HWC_DISPLAY_PRIMARY && pfd[dpy][ev].fd < 0) {
+                // Make sure fb device is opened before starting
+                // this thread so this never happens.
+                ALOGE ("%s:unable to open event node for dpy=%d event=%zu, %s",
+                        __FUNCTION__, dpy, ev, strerror(errno));
+                if (ev == 0) {
+                    ctx->vstate.fakevsync = true;
+                    //XXX: Blank events don't work with fake vsync,
+                    //but we shouldn't be running on fake vsync anyway.
+                    break;
+                }
             }
-        }
-        // Read once from the fds to clear the first notify
-        pread(fb_fd[dpy], vdata , MAX_DATA, 0);
 
-        pfd[dpy].fd = fb_fd[dpy];
-        if (pfd[dpy].fd >= 0)
-            pfd[dpy].events = POLLPRI | POLLERR;
+            pread(pfd[dpy][ev].fd, vdata , MAX_DATA, 0);
+            if (pfd[dpy][ev].fd >= 0)
+                pfd[dpy][ev].events = POLLPRI | POLLERR;
+        }
     }
 
     if (LIKELY(!ctx->vstate.fakevsync)) {
         do {
-            int err = poll(pfd, num_displays, -1);
+            int err = poll(*pfd, num_displays * num_events, -1);
             if(err > 0) {
                 for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
-                    if (pfd[dpy].revents & POLLPRI) {
-                        int len = pread(pfd[dpy].fd, vdata, MAX_DATA, 0);
-                        if (UNLIKELY(len < 0)) {
-                            // If the read was just interrupted - it is not a
-                            // fatal error. Just continue in this case
-                            ALOGE ("%s: Unable to read vsync for dpy=%d : %s",
-                                    __FUNCTION__, dpy, strerror(errno));
-                            continue;
+                    for(size_t ev = 0; ev < num_events; ev++) {
+                        if (pfd[dpy][ev].revents & POLLPRI) {
+                            err = pread(pfd[dpy][ev].fd, vdata, MAX_DATA, 0);
+                            if (UNLIKELY(err < 0)) {
+                                // If the read was just interrupted - it is not
+                                // a fatal error. Just continue in this case
+                                ALOGE ("%s: Unable to read event:%zu for \
+                                        dpy=%d : %s",
+                                        __FUNCTION__, ev, dpy, strerror(errno));
+                                continue;
+                            }
+                            event_list[ev].callback(ctx, dpy, vdata);
                         }
-                        // extract timestamp
-                        if (!strncmp(vdata, "VSYNC=", strlen("VSYNC="))) {
-                            timestamp[dpy] = strtoull(vdata + strlen("VSYNC="),
-                                    NULL, 0);
-                        }
-                        // send timestamp to SurfaceFlinger
-                        ALOGD_IF (logvsync,
-                            "%s: timestamp %"PRIu64" sent to SF for dpy=%d",
-                            __FUNCTION__, timestamp[dpy], dpy);
-                        ctx->proc->vsync(ctx->proc, dpy, timestamp[dpy]);
                     }
                 }
-
             } else {
-                ALOGE("%s: vsync poll failed errno: %s", __FUNCTION__,
+                ALOGE("%s: poll failed errno: %s", __FUNCTION__,
                         strerror(errno));
                 continue;
             }
@@ -157,16 +185,17 @@
         //Also, fake vsync is delivered only for the primary display.
         do {
             usleep(16666);
-            timestamp[HWC_DISPLAY_PRIMARY] = systemTime();
-            ctx->proc->vsync(ctx->proc, HWC_DISPLAY_PRIMARY,
-                    timestamp[HWC_DISPLAY_PRIMARY]);
+            uint64_t timestamp = systemTime();
+            ctx->proc->vsync(ctx->proc, HWC_DISPLAY_PRIMARY, timestamp);
 
         } while (true);
     }
 
     for (int dpy = HWC_DISPLAY_PRIMARY; dpy <= HWC_DISPLAY_EXTERNAL; dpy++ ) {
-        if(fb_fd[dpy] >= 0)
-            close (fb_fd[dpy]);
+        for( size_t event = 0; event < num_events; event++) {
+            if(pfd[dpy][event].fd >= 0)
+                close (pfd[dpy][event].fd);
+        }
     }
 
     return NULL;
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index 9ee2d8d..a757e69 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -68,15 +68,13 @@
     mMDPUpscale = 0;
     mMDPDownscale = 0;
     mMacroTileEnabled = false;
-    mPanelType = NO_PANEL;
     mLowBw = 0;
     mHighBw = 0;
     mSourceSplit = false;
     mRGBHasNoScalar = false;
 
-    if(!updatePanelInfo()) {
-        ALOGE("Unable to read Primary Panel Information");
-    }
+    updatePanelInfo();
+
     if(!updateSysFsInfo()) {
         ALOGE("Unable to read display sysfs node");
     }
@@ -116,10 +114,12 @@
 }
 // This function reads the sysfs node to read the primary panel type
 // and updates information accordingly
-bool MDPVersion::updatePanelInfo() {
+void  MDPVersion::updatePanelInfo() {
     FILE *displayDeviceFP = NULL;
+    FILE *panelInfoNodeFP = NULL;
     const int MAX_FRAME_BUFFER_NAME_SIZE = 128;
     char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
+    char panelInfo[MAX_FRAME_BUFFER_NAME_SIZE];
     const char *strCmdPanel = "mipi dsi cmd panel";
     const char *strVideoPanel = "mipi dsi video panel";
     const char *strLVDSPanel = "lvds panel";
@@ -130,21 +130,62 @@
         fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
                 displayDeviceFP);
         if(strncmp(fbType, strCmdPanel, strlen(strCmdPanel)) == 0) {
-            mPanelType = MIPI_CMD_PANEL;
+            mPanelInfo.mType = MIPI_CMD_PANEL;
         }
         else if(strncmp(fbType, strVideoPanel, strlen(strVideoPanel)) == 0) {
-            mPanelType = MIPI_VIDEO_PANEL;
+            mPanelInfo.mType = MIPI_VIDEO_PANEL;
         }
         else if(strncmp(fbType, strLVDSPanel, strlen(strLVDSPanel)) == 0) {
-            mPanelType = LVDS_PANEL;
+            mPanelInfo.mType = LVDS_PANEL;
         }
         else if(strncmp(fbType, strEDPPanel, strlen(strEDPPanel)) == 0) {
-            mPanelType = EDP_PANEL;
+            mPanelInfo.mType = EDP_PANEL;
         }
         fclose(displayDeviceFP);
-        return true;
-    }else {
-        return false;
+    } else {
+        ALOGE("Unable to read Primary Panel Information");
+    }
+
+    panelInfoNodeFP = fopen("/sys/class/graphics/fb0/msm_fb_panel_info", "r");
+    if(panelInfoNodeFP){
+        size_t len = PAGE_SIZE;
+        ssize_t read;
+        char *readLine = (char *) malloc (len);
+        while((read = getline((char **)&readLine, &len,
+                              panelInfoNodeFP)) != -1) {
+            int token_ct=0;
+            char *tokens[10];
+            memset(tokens, 0, sizeof(tokens));
+
+            if(!tokenizeParams(readLine, TOKEN_PARAMS_DELIM, tokens,
+                               &token_ct)) {
+                if(!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
+                    mPanelInfo.mPartialUpdateEnable = atoi(tokens[1]);
+                    ALOGI("PartialUpdate status: %s",
+                          mPanelInfo.mPartialUpdateEnable? "Enabled" :
+                          "Disabled");
+                }
+                if(!strncmp(tokens[0], "xalign", strlen("xalign"))) {
+                    mPanelInfo.mLeftAlign = atoi(tokens[1]);
+                    ALOGI("Left Align: %d", mPanelInfo.mLeftAlign);
+                }
+                if(!strncmp(tokens[0], "walign", strlen("walign"))) {
+                    mPanelInfo.mWidthAlign = atoi(tokens[1]);
+                    ALOGI("Width Align: %d", mPanelInfo.mWidthAlign);
+                }
+                if(!strncmp(tokens[0], "ystart", strlen("ystart"))) {
+                    mPanelInfo.mTopAlign = atoi(tokens[1]);
+                    ALOGI("Top Align: %d", mPanelInfo.mTopAlign);
+                }
+                if(!strncmp(tokens[0], "halign", strlen("halign"))) {
+                    mPanelInfo.mHeightAlign = atoi(tokens[1]);
+                    ALOGI("Height Align: %d", mPanelInfo.mHeightAlign);
+                }
+            }
+        }
+        fclose(panelInfoNodeFP);
+    } else {
+        ALOGE("Failed to open msm_fb_panel_info node");
     }
 }
 
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index 04c84cd..aab8643 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -92,13 +92,25 @@
     friend class MDPVersion;
 };
 
+struct PanelInfo {
+    char mType;                  // Smart or Dumb
+    int mPartialUpdateEnable;    // Partial update feature
+    int mLeftAlign;              // ROI left alignment restriction
+    int mWidthAlign;             // ROI width alignment restriction
+    int mTopAlign;               // ROI top alignment restriction
+    int mHeightAlign;            // ROI height alignment restriction
+    PanelInfo() : mType(NO_PANEL), mPartialUpdateEnable(0),
+    mLeftAlign(0), mWidthAlign(0), mTopAlign(0), mHeightAlign(0){}
+    friend class MDPVersion;
+};
+
 class MDPVersion : public Singleton <MDPVersion>
 {
 public:
     MDPVersion();
     ~MDPVersion();
     int getMDPVersion() {return mMDPVersion;}
-    char getPanelType() {return mPanelType;}
+    char getPanelType() {return mPanelInfo.mType;}
     bool hasOverlay() {return mHasOverlay;}
     uint8_t getTotalPipes() {
         return (uint8_t)(mRGBPipes + mVGPipes + mDMAPipes);
@@ -113,6 +125,11 @@
     bool supportsMacroTile();
     int getLeftSplit() { return mSplit.left(); }
     int getRightSplit() { return mSplit.right(); }
+    int isPartialUpdateEnabled() { return mPanelInfo.mPartialUpdateEnable; }
+    int getLeftAlign() { return mPanelInfo.mLeftAlign; }
+    int getWidthAlign() { return mPanelInfo.mWidthAlign; }
+    int getTopAlign() { return mPanelInfo.mTopAlign; }
+    int getHeightAlign() { return mPanelInfo.mHeightAlign; }
     unsigned long getLowBw() { return mLowBw; }
     unsigned long getHighBw() { return mHighBw; }
     bool isSrcSplit() const;
@@ -125,13 +142,12 @@
 
 private:
     bool updateSysFsInfo();
-    bool updatePanelInfo();
+    void updatePanelInfo();
     bool updateSplitInfo();
     int tokenizeParams(char *inputParams, const char *delim,
                         char* tokenStr[], int *idx);
     int mFd;
     int mMDPVersion;
-    char mPanelType;
     bool mHasOverlay;
     uint32_t mMdpRev;
     uint8_t mRGBPipes;
@@ -142,6 +158,7 @@
     uint32_t mMDPUpscale;
     bool mMacroTileEnabled;
     Split mSplit;
+    PanelInfo mPanelInfo;
     unsigned long mLowBw; //kbps
     unsigned long mHighBw; //kbps
     bool mSourceSplit;