Merge "hwc: Add a new check for DMA state change"
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index 421f531..da18c7b 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -584,7 +584,6 @@
     struct blitReq list1;
     memset((char *)&list1 , 0 ,sizeof (struct blitReq) );
     list1.count = 1;
-    int rel_fen_fd = -1;
     int my_tmp_get_fence = -1;
 
     list1.sync.acq_fen_fd  =  ctx->acqFence;
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index b13166d..4167ae2 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -296,6 +296,7 @@
             // for targets/OEMs which do not need HW level protection
             // do not set ion secure flag & MM heap. Fallback to IOMMU heap.
             ionFlags |= ION_HEAP(ION_IOMMU_HEAP_ID);
+            data.allocType |= private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER;
         }
     } else if(usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
         //MM Heap is exclusively a secure heap.
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 75b8349..d64914e 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -193,6 +193,8 @@
             PRIV_FLAGS_NOT_MAPPED         = 0x00001000,
             // Display on external only
             PRIV_FLAGS_EXTERNAL_ONLY      = 0x00002000,
+            // Set by HWC for protected non secure buffers
+            PRIV_FLAGS_PROTECTED_BUFFER   = 0x00004000,
             PRIV_FLAGS_VIDEO_ENCODER      = 0x00010000,
             PRIV_FLAGS_CAMERA_WRITE       = 0x00020000,
             PRIV_FLAGS_CAMERA_READ        = 0x00040000,
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 43ae916..3e16072 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -157,6 +157,8 @@
         }
 
         ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_SMP_FORCE_ALLOC);
         ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
 
         hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
@@ -280,6 +282,8 @@
 
         overlay::Overlay& ov = *(ctx->mOverlay);
         ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_SMP_FORCE_ALLOC);
         ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
         ovutils::eTransform orient =
             static_cast<ovutils::eTransform>(layer->transform);
@@ -442,6 +446,8 @@
                 mTileEnabled));
 
     ovutils::eMdpFlags mdpFlags = OV_MDP_BLEND_FG_PREMULT;
+    ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_SMP_FORCE_ALLOC);
     ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
 
     ovutils::PipeArgs parg(mdpFlags,
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index baeb1b9..56d86ec 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;
@@ -2069,7 +2083,7 @@
                              PipeLayerPair& PipeLayerPair) {
     MdpPipeInfoNonSplit& mdp_info =
         *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
-    eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
+    eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
     eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
     eDest dest = mdp_info.index;
 
@@ -2125,7 +2139,7 @@
     MdpYUVPipeInfo& mdp_info =
             *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
     eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
-    eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
+    eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
     eDest lDest = mdp_info.lIndex;
     eDest rDest = mdp_info.rIndex;
 
@@ -2357,7 +2371,7 @@
         MdpYUVPipeInfo& mdp_info =
                 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
         eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
-        eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
+        eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
         eDest lDest = mdp_info.lIndex;
         eDest rDest = mdp_info.rIndex;
 
@@ -2377,7 +2391,7 @@
     MdpPipeInfoSplit& mdp_info =
         *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
     eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
-    eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
+    eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
     eDest lDest = mdp_info.lIndex;
     eDest rDest = mdp_info.rIndex;
 
@@ -2624,7 +2638,7 @@
     calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
 
     int downscale = getRotDownscale(ctx, layer);
-    eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
+    eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
     setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
 
     if(lDest != OV_INVALID && rDest != OV_INVALID) {
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..0af8090 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -184,7 +184,7 @@
             handle_resume(ctx, dpy);
         }
     } else {
-        ALOGE("%s: Invalid dpy", __FUNCTION__, dpy);
+        ALOGE("%s: Invalid dpy %d", __FUNCTION__, dpy);
         return;
     }
 }
@@ -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.cpp b/libhwcomposer/hwc_utils.cpp
index 6a74625..b091ae2 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -856,6 +856,9 @@
     src_w = sourceCrop.right - sourceCrop.left;
     src_h = sourceCrop.bottom - sourceCrop.top;
 
+    if(layer->transform & HWC_TRANSFORM_ROT_90)
+        swap(src_w, src_h);
+
     if(((src_w != dst_w) || (src_h != dst_h)))
         return true;
 
@@ -1672,6 +1675,13 @@
     if(isSecureBuffer(hnd)) {
         ovutils::setMdpFlags(mdpFlags,
                 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_SMP_FORCE_ALLOC);
+    }
+
+    if(isProtectedBuffer(hnd)) {
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_SMP_FORCE_ALLOC);
     }
 
     if(isSecureDisplayBuffer(hnd)) {
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 330d22d..96d1e58 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
@@ -463,6 +464,12 @@
     return (hnd && (private_handle_t::PRIV_FLAGS_SECURE_BUFFER & hnd->flags));
 }
 
+// Returns true if the buffer is protected
+static inline bool isProtectedBuffer(const private_handle_t* hnd) {
+    return (hnd && (private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER & hnd->flags));
+}
+
+
 static inline bool isTileRendered(const private_handle_t* hnd) {
     return (hnd && (private_handle_t::PRIV_FLAGS_TILE_RENDERED & hnd->flags));
 }
diff --git a/libhwcomposer/hwc_vsync.cpp b/libhwcomposer/hwc_vsync.cpp
index 7b97c6c..722916a 100644
--- a/libhwcomposer/hwc_vsync.cpp
+++ b/libhwcomposer/hwc_vsync.cpp
@@ -88,9 +88,10 @@
         thermalLevel = strtoull(data + strlen("thermal_level="), NULL, 0);
     }
 
-    if (thermalLevel >= MAX_THERMAL_LEVEL)
+    if (thermalLevel >= MAX_THERMAL_LEVEL) {
+        ALOGD("%s: dpy:%d thermal_level=%"PRIu64"",__FUNCTION__,dpy,thermalLevel);
         ctx->mThermalBurstMode = true;
-    else
+    } else
         ctx->mThermalBurstMode = false;
 }
 
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index 96c057f..3a96b71 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -279,8 +279,29 @@
     uint8_t pipe2Prio = mPipeBook[(int)pipe2Index].mPipe->getPriority();
     if(pipe1Prio > pipe2Prio)
         return -1;
-    if(pipe1Prio < pipe2Prio)
+    else if(pipe1Prio < pipe2Prio)
         return 1;
+    else {
+        // If we are here, Source Split is enabled and both pipes are
+        // new requests. In this case left type should be of higher prio
+        // than right type
+        utils::eMdpPipeType leftType = PipeBook::getPipeType(pipe1Index);
+        utils::eMdpPipeType rightType = PipeBook::getPipeType(pipe2Index);
+
+        if(leftType == rightType) {
+            //Safe. Onus on driver to assign correct pipes within same type
+            return 1;
+        } else if(leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG) {
+            //If we are here, right is definitely a higher prio type.
+            //This check takes advantage of having only 3 types and avoids 3
+            //different failure combination checks.
+            return -1;
+        } else {
+            //Types are correct priority-wise
+            return 1;
+        }
+    }
+
     return 0;
 }
 
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index ff6d4ef..54ee0fd 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -223,7 +223,6 @@
     OV_MDP_SECURE_OVERLAY_SESSION = MDP_SECURE_OVERLAY_SESSION,
     OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION = MDP_SECURE_DISPLAY_OVERLAY_SESSION,
     OV_MDP_SOURCE_ROTATED_90 = MDP_SOURCE_ROTATED_90,
-    OV_MDP_BACKEND_COMPOSITION = MDP_BACKEND_COMPOSITION,
     OV_MDP_BLEND_FG_PREMULT = MDP_BLEND_FG_PREMULT,
     OV_MDP_FLIP_H = MDP_FLIP_LR,
     OV_MDP_FLIP_V = MDP_FLIP_UD,
@@ -232,6 +231,7 @@
     OV_MDSS_MDP_BWC_EN = MDP_BWC_EN,
     OV_MDSS_MDP_DUAL_PIPE = MDSS_MDP_DUAL_PIPE,
     OV_MDP_SOLID_FILL = MDP_SOLID_FILL,
+    OV_MDP_SMP_FORCE_ALLOC = MDP_SMP_FORCE_ALLOC,
 };
 
 enum eZorder {
@@ -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