Merge "hwc: Handle idle fallback in corner cases"
diff --git a/common.mk b/common.mk
index a2283c4..cdac0fa 100644
--- a/common.mk
+++ b/common.mk
@@ -7,11 +7,6 @@
 common_includes += $(LOCAL_PATH)/../libhdmi
 common_includes += $(LOCAL_PATH)/../libqservice
 
-ifeq ($(TARGET_USES_POST_PROCESSING),true)
-    common_flags     += -DUSES_POST_PROCESSING
-    common_includes  += $(TARGET_OUT_HEADERS)/pp/inc
-endif
-
 common_header_export_path := qcom/display
 
 #Common libraries external to display HAL
@@ -21,6 +16,11 @@
 common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
 common_flags += -Wconversion -Wall -Werror
 
+ifeq ($(TARGET_USES_POST_PROCESSING),true)
+    common_flags     += -DUSES_POST_PROCESSING
+    common_includes  += $(TARGET_OUT_HEADERS)/pp/inc
+endif
+
 ifeq ($(ARCH_ARM_HAVE_NEON),true)
     common_flags += -D__ARM_HAVE_NEON
 endif
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 4167ae2..cd6d565 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -292,6 +292,11 @@
         if (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
             ionFlags |= ION_HEAP(ION_CP_MM_HEAP_ID);
             ionFlags |= ION_SECURE;
+#ifdef ION_FLAG_ALLOW_NON_CONTIG
+            if (!(usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY)) {
+                ionFlags |= ION_FLAG_ALLOW_NON_CONTIG;
+            }
+#endif
         } else {
             // for targets/OEMs which do not need HW level protection
             // do not set ion secure flag & MM heap. Fallback to IOMMU heap.
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 9b98f1b..551f188 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -141,6 +141,14 @@
             flags |= private_handle_t::PRIV_FLAGS_HW_TEXTURE;
         }
 
+        if (usage & GRALLOC_USAGE_HW_RENDER) {
+            flags |= private_handle_t::PRIV_FLAGS_HW_RENDER;
+        }
+
+        if (usage & GRALLOC_USAGE_HW_FB) {
+            flags |= private_handle_t::PRIV_FLAGS_HW_FB;
+        }
+
         if(usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY) {
             flags |= private_handle_t::PRIV_FLAGS_SECURE_DISPLAY;
         }
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index d64914e..9e2a6cf 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -182,10 +182,9 @@
             PRIV_FLAGS_NEEDS_FLUSH        = 0x00000020,
             // Uncached memory or no CPU writers
             PRIV_FLAGS_DO_NOT_FLUSH       = 0x00000040,
-            PRIV_FLAGS_SW_LOCK            = 0x00000080,
+            PRIV_FLAGS_HW_RENDER          = 0x00000080,
             PRIV_FLAGS_NONCONTIGUOUS_MEM  = 0x00000100,
-            // Set by HWC when storing the handle
-            PRIV_FLAGS_HWC_LOCK           = 0x00000200,
+            PRIV_FLAGS_HW_FB              = 0x00000200,
             PRIV_FLAGS_SECURE_BUFFER      = 0x00000400,
             // For explicit synchronization
             PRIV_FLAGS_UNSYNCHRONIZED     = 0x00000800,
diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp
index 23e225d..91a930c 100644
--- a/libgralloc/ionalloc.cpp
+++ b/libgralloc/ionalloc.cpp
@@ -77,12 +77,18 @@
     ionAllocData.len = data.size;
     ionAllocData.align = data.align;
     ionAllocData.heap_id_mask = data.flags & ~ION_SECURE;
+#ifdef ION_FLAG_ALLOW_NON_CONTIG
+    ionAllocData.heap_id_mask &= (data.flags & ~ION_FLAG_ALLOW_NON_CONTIG);
+#endif
     ionAllocData.flags = data.uncached ? 0 : ION_FLAG_CACHED;
     // ToDo: replace usage of alloc data structure with
     //  ionallocdata structure.
     if (data.flags & ION_SECURE)
         ionAllocData.flags |= ION_SECURE;
-
+#ifdef ION_FLAG_ALLOW_NON_CONTIG
+    if (data.flags & ION_FLAG_ALLOW_NON_CONTIG)
+        ionAllocData.flags |= ION_FLAG_ALLOW_NON_CONTIG;
+#endif
     err = open_device();
     if (err)
         return err;
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 943e64f..3053d47 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -238,11 +238,11 @@
         }
         if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION and
                     not useUncached(usage)) {
-            bool nonCPUWriters = usage & (
-                        GRALLOC_USAGE_HW_RENDER |
-                        GRALLOC_USAGE_HW_FB |
-                        GRALLOC_USAGE_HW_VIDEO_ENCODER |
-                        GRALLOC_USAGE_HW_CAMERA_WRITE);
+            bool nonCPUWriters = hnd->flags & (
+                        private_handle_t::PRIV_FLAGS_HW_RENDER |
+                        private_handle_t::PRIV_FLAGS_HW_FB |
+                        private_handle_t::PRIV_FLAGS_VIDEO_ENCODER |
+                        private_handle_t::PRIV_FLAGS_CAMERA_WRITE);
 
             //Invalidate if CPU reads in software and there are non-CPU
             //writers. No need to do this for the metadata buffer as it is
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index c96eb1e..22b576e 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -475,10 +475,11 @@
                 return -errno;
             }
 
-            if(mode == HWC_POWER_MODE_NORMAL) {
+            if(mode == HWC_POWER_MODE_NORMAL && !ctx->mHPDEnabled) {
                 // Enable HPD here, as during bootup POWER_MODE_NORMAL is set
                 // when SF is completely initialized
                 ctx->mHDMIDisplay->setHPD(1);
+                ctx->mHPDEnabled = true;
             }
 
             ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 1c390ef..8e62b61 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -26,6 +26,7 @@
 #include "hwc_ad.h"
 #include <overlayRotator.h>
 #include "hwc_copybit.h"
+#include "qd_utils.h"
 
 using namespace overlay;
 using namespace qdutils;
@@ -48,6 +49,7 @@
 bool MDPComp::sSrcSplitEnabled = false;
 int MDPComp::sMaxSecLayers = 1;
 bool MDPComp::enablePartialUpdateForMDP3 = false;
+bool MDPComp::sIsPartialUpdateActive = true;
 MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
     if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
         sSrcSplitEnabled = true;
@@ -131,9 +133,7 @@
 
     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;
+    sMaxPipesPerMixer = (int)mdpVersion.getBlendStages();
     if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
         int val = atoi(property);
         if(val >= 0)
@@ -192,6 +192,8 @@
        enablePartialUpdateForMDP3 = true;
     }
 
+    sIsPartialUpdateActive = getPartialUpdatePref(ctx);
+
     return true;
 }
 
@@ -231,7 +233,7 @@
 
 void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
     qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
-    uint32_t maxSupported = (int)mdpVersion.getBlendStages() - 2;
+    uint32_t maxSupported = (int)mdpVersion.getBlendStages();
     if(value > maxSupported) {
         ALOGW("%s: Input exceeds max value supported. Setting to"
                 "max value: %d", __FUNCTION__, maxSupported);
@@ -1264,7 +1266,7 @@
         hwc_display_contents_1_t* list){
     if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
             isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
-            mDpy ) {
+            !sIsPartialUpdateActive || mDpy ) {
         return false;
     }
     if(ctx->listStats[mDpy].secureUI)
@@ -2753,5 +2755,49 @@
     return 0;
 }
 
+bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
+    Locker::Autolock _l(ctx->mDrawLock);
+    const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
+    char path[MAX_SYSFS_FILE_PATH];
+    snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
+    int fd = open(path, O_RDONLY);
+    if(fd < 0) {
+        ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
+        return -1;
+    }
+    char value[4];
+    ssize_t size_read = read(fd, value, sizeof(value)-1);
+    if(size_read <= 0) {
+        ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
+        close(fd);
+        return -1;
+    }
+    close(fd);
+    value[size_read] = '\0';
+    return atoi(value);
+}
+
+int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
+    Locker::Autolock _l(ctx->mDrawLock);
+    const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
+    char path[MAX_SYSFS_FILE_PATH];
+    snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
+    int fd = open(path, O_WRONLY);
+    if(fd < 0) {
+        ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
+        return -1;
+    }
+    char value[4];
+    snprintf(value, sizeof(value), "%d", (int)enable);
+    ssize_t ret = write(fd, value, strlen(value));
+    if(ret <= 0) {
+        ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
+        close(fd);
+        return -1;
+    }
+    close(fd);
+    sIsPartialUpdateActive = enable;
+    return 0;
+}
 }; //namespace
 
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 8929c40..3ce4a64 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -56,7 +56,8 @@
     static void dynamicDebug(bool enable){ sDebugLogs = enable; }
     static void setIdleTimeout(const uint32_t& timeout);
     static void setMaxPipesPerMixer(const uint32_t value);
-
+    static int setPartialUpdatePref(hwc_context_t *ctx, bool enable);
+    static bool getPartialUpdatePref(hwc_context_t *ctx);
 protected:
     enum ePipeType {
         MDPCOMP_OV_RGB = ovutils::OV_MDP_PIPE_RGB,
@@ -257,6 +258,7 @@
     static bool sSrcSplitEnabled;
     static IdleInvalidator *sIdleInvalidator;
     static int sMaxSecLayers;
+    static bool sIsPartialUpdateActive;
     struct FrameInfo mCurrentFrame;
     struct LayerCache mCachedFrame;
     //Enable 4kx2k yuv layer split
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index b0ebb3a..add5dc8 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -306,6 +306,13 @@
     }
 }
 
+static status_t setPartialUpdatePref(hwc_context_t *ctx, uint32_t enable) {
+    ALOGD("%s: enable: %d", __FUNCTION__, enable);
+    if(qhwc::MDPComp::setPartialUpdatePref(ctx, (bool)enable) < 0)
+        return NO_INIT;
+    return NO_ERROR;
+}
+
 status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
         Parcel* outParcel) {
     status_t ret = NO_ERROR;
@@ -353,6 +360,8 @@
             break;
         case IQService::SET_MAX_PIPES_PER_MIXER:
             setMaxPipesPerMixer(mHwcContext, inParcel);
+        case IQService::SET_PARTIAL_UPDATE:
+            ret = setPartialUpdatePref(mHwcContext, inParcel->readInt32());
             break;
         case IQService::TOGGLE_BWC:
             toggleBWC(mHwcContext, inParcel);
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index ace0017..bcac4be 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -413,6 +413,7 @@
     }
 
     memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
+    ctx->mHPDEnabled = false;
     ALOGI("Initializing Qualcomm Hardware Composer");
     ALOGI("MDP version: %d", ctx->mMDP.version);
 }
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 286ae22..29c0cc9 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -479,11 +479,6 @@
     return (hnd && (private_handle_t::PRIV_FLAGS_TILE_RENDERED & hnd->flags));
 }
 
-//Return true if buffer is marked locked
-static inline bool isBufferLocked(const private_handle_t* hnd) {
-    return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
-}
-
 //Return true if the buffer is intended for Secure Display
 static inline bool isSecureDisplayBuffer(const private_handle_t* hnd) {
     return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY));
@@ -644,6 +639,8 @@
     bool mBWCEnabled;
     // Provides a way for OEM's to disable setting dynfps via metadata.
     bool mUseMetaDataRefreshRate;
+   // Stores the hpd enabled status- avoids re-enabling HDP on suspend resume.
+    bool mHPDEnabled;
 };
 
 namespace qhwc {
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index e9c0a13..c250919 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -47,6 +47,9 @@
 
     initScalar();
     setDMAMultiplexingSupported();
+#ifdef USES_POST_PROCESSING
+    initPostProc();
+#endif
 }
 
 Overlay::~Overlay() {
@@ -54,6 +57,9 @@
         mPipeBook[i].destroy();
     }
     destroyScalar();
+#ifdef USES_POST_PROCESSING
+    destroyPostProc();
+#endif
 }
 
 void Overlay::configBegin() {
@@ -526,6 +532,23 @@
     }
 }
 
+void Overlay::initPostProc() {
+    sLibAblHandle = dlopen("libmm-abl.so", RTLD_NOW);
+    if (sLibAblHandle) {
+        *(void **)&sFnppParams = dlsym(sLibAblHandle,
+                                       "display_pp_compute_params");
+    } else {
+        ALOGE("%s: Not able to load libmm-abl.so", __FUNCTION__);
+    }
+}
+
+void Overlay::destroyPostProc() {
+    if (sLibAblHandle) {
+        dlclose(sLibAblHandle);
+        sLibAblHandle = NULL;
+    }
+}
+
 void Overlay::PipeBook::init() {
     mPipe = NULL;
     mDisplay = DPY_UNUSED;
@@ -557,5 +580,9 @@
     {utils::OV_MDP_PIPE_ANY};
 void *Overlay::sLibScaleHandle = NULL;
 int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
+/* Dynamically link ABL library */
+void *Overlay::sLibAblHandle = NULL;
+int (*Overlay::sFnppParams)(const struct compute_params *,
+                            struct mdp_overlay_pp_params *) = NULL;
 
 }; // namespace overlay
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 665e23f..984b439 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -33,6 +33,9 @@
 #include "overlayUtils.h"
 #include "mdp_version.h"
 #include "utils/threads.h"
+#ifdef USES_POST_PROCESSING
+#include "lib-postproc.h"
+#endif
 
 struct MetaData_t;
 
@@ -186,6 +189,12 @@
     /* Sets the pipe type RGB/VG/DMA*/
     void setPipeType(utils::eDest pipeIndex, const utils::eMdpPipeType pType);
 
+    /* Dynamically link ABL library */
+    static void initPostProc();
+    static void destroyPostProc();
+    static int (*getFnPpParams())(const struct compute_params *,
+                                 struct mdp_overlay_pp_params *);
+
     /* Just like a Facebook for pipes, but much less profile info */
     struct PipeBook {
         void init();
@@ -251,6 +260,10 @@
     static bool sDMAMultiplexingSupported;
     static void *sLibScaleHandle;
     static int (*sFnProgramScale)(struct mdp_overlay_list *);
+    /* Dynamically link ABL library */
+    static void *sLibAblHandle;
+    static int (*sFnppParams)(const struct compute_params *,
+                            struct mdp_overlay_pp_params *);
     static bool sDebugPipeLifecycle;
 
     friend class MdpCtrl;
@@ -345,6 +358,11 @@
     return sFnProgramScale;
 }
 
+inline int (*Overlay::getFnPpParams())(const struct compute_params *,
+                    struct mdp_overlay_pp_params *) {
+    return sFnppParams;
+}
+
 inline void Overlay::debugPipeLifecycle(const bool& enable) {
     sDebugPipeLifecycle = enable;
 }
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 4cd52a7..3932c4c 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -21,6 +21,7 @@
 #include "overlayMdp.h"
 #include "mdp_version.h"
 #include <overlay.h>
+#include <dlfcn.h>
 
 #define HSIC_SETTINGS_DEBUG 0
 
@@ -263,7 +264,7 @@
         }
 
         if (needUpdate) {
-            mParams.params.pa_params.hue = data.hsicData.hue;
+            mParams.params.pa_params.hue = (float)data.hsicData.hue;
             mParams.params.pa_params.sat = data.hsicData.saturation;
             mParams.params.pa_params.intensity = data.hsicData.intensity;
             mParams.params.pa_params.contrast = data.hsicData.contrast;
@@ -333,7 +334,15 @@
     }
 
     if (needUpdate) {
-        display_pp_compute_params(&mParams, &mOVInfo.overlay_pp_cfg);
+        int (*sFnppParams)(const struct compute_params *,
+                           struct mdp_overlay_pp_params *) =
+                           Overlay::getFnPpParams();
+        if(sFnppParams) {
+           int ret = sFnppParams(&mParams, &mOVInfo.overlay_pp_cfg);
+           if (ret) {
+             ALOGE("%s: Unable to set PP params", __FUNCTION__);
+           }
+        }
     }
 #endif
     return true;
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index f8729a5..8ca0824 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -101,7 +101,7 @@
     mSourceSplitAlways = false;
     mRGBHasNoScalar = false;
     mRotDownscale = false;
-    mBlendStages = 6; //min no. of stages supported by MDP.
+    mBlendStages = 4; //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.
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 683c93c..a935131 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -55,8 +55,9 @@
         DYNAMIC_DEBUG = 15,     // Enable more logging on the fly
         SET_IDLE_TIMEOUT = 16,  // Set idle timeout for GPU fallback
         TOGGLE_BWC = 17,           // Toggle BWC On/Off on targets that support
+        SET_PARTIAL_UPDATE = 18,   // Preference on partial update feature
         /* Enable/Disable/Set refresh rate dynamically */
-        CONFIGURE_DYN_REFRESH_RATE = 18,
+        CONFIGURE_DYN_REFRESH_RATE = 19,
         COMMAND_LIST_END = 400,
     };
 
diff --git a/libqservice/QServiceUtils.h b/libqservice/QServiceUtils.h
index f53d140..5b61c8e 100644
--- a/libqservice/QServiceUtils.h
+++ b/libqservice/QServiceUtils.h
@@ -74,6 +74,10 @@
     return sendSingleParam(qService::IQService::SCREEN_REFRESH, 1);
 }
 
+inline android::status_t setPartialUpdate(uint32_t enable) {
+    return sendSingleParam(qService::IQService::SET_PARTIAL_UPDATE, enable);
+}
+
 inline android::status_t setExtOrientation(uint32_t orientation) {
     return sendSingleParam(qService::IQService::EXTERNAL_ORIENTATION,
             orientation);