hwc: Query MDP capability for blending stages supported.

- Read MDP sys_fs node for blending stages supported per mixer
  instead of hard cording the value. This makes the implementation
  scalable across chipsets.
- Add binder support to change the max pipes per layer value
  dynamically for MDP comp.

Change-Id: I3b83f4bdc2e2e81ca55c54fc6bcfd61c55fef501
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 2904e6f..d808a97 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -43,7 +43,7 @@
 bool MDPComp::sEnabled = false;
 bool MDPComp::sEnableMixedMode = true;
 int MDPComp::sSimulationFlags = 0;
-int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
+int MDPComp::sMaxPipesPerMixer = 0;
 bool MDPComp::sEnableYUVsplit = false;
 bool MDPComp::sSrcSplitEnabled = false;
 bool MDPComp::enablePartialUpdateForMDP3 = false;
@@ -127,11 +127,15 @@
         sEnableMixedMode = false;
     }
 
-    sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
-    if(property_get("debug.mdpcomp.maxpermixer", property, "-1") > 0) {
+    qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
+
+    /* MDSS_MDP_STAGE_UNUSED and MDSS_MDP_STAGE_BASE are not available for MDP
+     * composition. */
+    sMaxPipesPerMixer = (int)mdpVersion.getBlendStages() - 2;
+    if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
         int val = atoi(property);
         if(val >= 0)
-            sMaxPipesPerMixer = min(val, MAX_PIPES_PER_MIXER);
+            sMaxPipesPerMixer = min(val, sMaxPipesPerMixer);
     }
 
     if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
@@ -213,6 +217,16 @@
     ctx->proc->invalidate(ctx->proc);
 }
 
+void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
+    qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
+    uint32_t maxSupported = (int)mdpVersion.getBlendStages() - 2;
+    if(value > maxSupported) {
+        ALOGW("%s: Input exceeds max value supported. Setting to"
+                "max value: %d", __FUNCTION__, maxSupported);
+    }
+    sMaxPipesPerMixer = min(value, maxSupported);
+}
+
 void MDPComp::setIdleTimeout(const uint32_t& timeout) {
     enum { ONE_REFRESH_PERIOD_MS = 17, ONE_BILLION_MS = 1000000000 };
 
@@ -268,7 +282,7 @@
 }
 
 void MDPComp::FrameInfo::reset(const int& numLayers) {
-    for(int i = 0; i < MAX_PIPES_PER_MIXER; i++) {
+    for(int i = 0 ; i < MAX_NUM_BLEND_STAGES; i++ ) {
         if(mdpToLayer[i].pipeInfo) {
             delete mdpToLayer[i].pipeInfo;
             mdpToLayer[i].pipeInfo = NULL;
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 4634fbc..7fa6674 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -25,8 +25,6 @@
 #include <cutils/properties.h>
 #include <overlay.h>
 
-#define MAX_PIPES_PER_MIXER 4
-
 namespace overlay {
 class Rotator;
 };
@@ -57,6 +55,7 @@
     static bool isIdleFallback() { return sIdleFallBack; }
     static void dynamicDebug(bool enable){ sDebugLogs = enable; }
     static void setIdleTimeout(const uint32_t& timeout);
+    static void setMaxPipesPerMixer(const uint32_t value);
 
 protected:
     enum { MAX_SEC_LAYERS = 1 }; //TODO add property support
@@ -104,7 +103,7 @@
 
         /* maps mdp list to layer list */
         int mdpCount;
-        struct PipeLayerPair mdpToLayer[MAX_PIPES_PER_MIXER];
+        struct PipeLayerPair mdpToLayer[MAX_NUM_BLEND_STAGES];
 
         /* layer composing on FB? */
         int fbCount;
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index fd0a36c..8e8066e 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -244,6 +244,13 @@
     MDPComp::setIdleTimeout(timeout);
 }
 
+static void setMaxPipesPerMixer(hwc_context_t* ctx, const Parcel* inParcel) {
+    uint32_t value = (uint32_t)inParcel->readInt32();
+    ALOGD("%s : setting MaxPipesPerMixer: %d ", __FUNCTION__, value);
+    Locker::Autolock _sl(ctx->mDrawLock);
+    MDPComp::setMaxPipesPerMixer(value);
+}
+
 status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
         Parcel* outParcel) {
     status_t ret = NO_ERROR;
@@ -289,6 +296,9 @@
         case IQService::SET_IDLE_TIMEOUT:
             setIdleTimeout(mHwcContext, inParcel);
             break;
+        case IQService::SET_MAX_PIPES_PER_MIXER:
+            setMaxPipesPerMixer(mHwcContext, inParcel);
+            break;
         default:
             ret = NO_ERROR;
     }
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 3f903b1..921c3e5 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -41,6 +41,7 @@
 #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
 #define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
 #define MAX_NUM_APP_LAYERS 32
+#define MAX_NUM_BLEND_STAGES 16
 #define MIN_DISPLAY_XRES 200
 #define MIN_DISPLAY_YRES 200
 #define HWC_WFDDISPSYNC_LOG 0
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index ff6d4ef..c5774c9 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -239,6 +239,9 @@
     ZORDER_1,
     ZORDER_2,
     ZORDER_3,
+    ZORDER_4,
+    ZORDER_5,
+    ZORDER_6,
     Z_SYSTEM_ALLOC = 0xFFFF
 };
 
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index e3d3131..f8729a5 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -101,6 +101,7 @@
     mSourceSplitAlways = false;
     mRGBHasNoScalar = false;
     mRotDownscale = false;
+    mBlendStages = 6; //min no. of stages supported by MDP.
 
     // this is the default limit of mixer unless driver reports it.
     // For resolutions beyond this, we use dual/split overlay pipes.
@@ -303,6 +304,10 @@
                 else if(!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
                     mDMAPipes = (uint8_t)atoi(tokens[1]);
                 }
+                else if(!strncmp(tokens[0], "blending_stages",
+                                strlen("blending_stages"))) {
+                    mBlendStages = (uint8_t)atoi(tokens[1]);
+                }
                 else if(!strncmp(tokens[0], "max_downscale_ratio",
                                 strlen("max_downscale_ratio"))) {
                     mMDPDownscale = atoi(tokens[1]);
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index 3c7f6a3..dcde240 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -116,6 +116,7 @@
     uint8_t getRGBPipes() { return mRGBPipes; }
     uint8_t getVGPipes() { return mVGPipes; }
     uint8_t getDMAPipes() { return mDMAPipes; }
+    uint8_t getBlendStages() { return mBlendStages; }
     bool supportsDecimation();
     uint32_t getMaxMDPDownscale();
     uint32_t getMaxMDPUpscale();
@@ -163,6 +164,7 @@
     uint8_t mRGBPipes;
     uint8_t mVGPipes;
     uint8_t mDMAPipes;
+    uint8_t mBlendStages;
     uint32_t mFeatures;
     uint32_t mMDPDownscale;
     uint32_t mMDPUpscale;
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 87d51fc..6f2f0e3 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -50,7 +50,7 @@
         SET_HSIC_DATA,           // Set HSIC on dspp
         GET_DISPLAY_VISIBLE_REGION,  // Get the visibleRegion for dpy
         SET_SECONDARY_DISPLAY_STATUS,  // Sets secondary display status
-        UNUSED_SLOT,             // XXX: Unsed - New one can go here
+        SET_MAX_PIPES_PER_MIXER, // Set max pipes per mixer for MDPComp
         SET_VIEW_FRAME,          // Set view frame of display
         DYNAMIC_DEBUG,           // Enable more logging on the fly
         SET_IDLE_TIMEOUT,        // Set idle timeout for GPU fallback