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;