Merge "sde: resource manager: rotator resource allocation"
diff --git a/common.mk b/common.mk
index cdac0fa..768696a 100644
--- a/common.mk
+++ b/common.mk
@@ -27,15 +27,8 @@
 
 ifeq ($(call is-board-platform-in-list, $(MSM_VIDC_TARGET_LIST)), true)
     common_flags += -DVENUS_COLOR_FORMAT
-endif
-
-ifeq ($(call is-board-platform-in-list, msm8974 msm8226 msm8610 apq8084 \
-        mpq8092 msm_bronze msm8916 msm8994), true)
     common_flags += -DMDSS_TARGET
 endif
-ifeq ($(call is-board-platform-in-list, msm8909), true)
-    common_flags += -DVENUS_COLOR_FORMAT
-endif
 
 common_deps  :=
 kernel_includes :=
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
index 3a0f2d0..93bec4d 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -345,7 +345,7 @@
           timing_mode->back_porch_v + timing_mode->pulse_width_v;
       display_attributes->x_dpi = 0;
       display_attributes->y_dpi = 0;
-      display_attributes->fps = FLOAT(timing_mode->refresh_rate);
+      display_attributes->fps = FLOAT(timing_mode->refresh_rate) / 1000.0f;
       display_attributes->vsync_period_ns = UINT32(1000000000L / display_attributes->fps);
       display_attributes->split_left = display_attributes->x_pixels;
       if (display_attributes->x_pixels > hw_resource_.max_mixer_width) {
@@ -442,9 +442,28 @@
 DisplayError HWFrameBuffer::PowerOff(Handle device) {
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
 
-  if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_POWERDOWN) == -1) {
-    IOCTL_LOGE(FB_BLANK_POWERDOWN, hw_context->type);
-    return kErrorHardware;
+  switch (hw_context->type) {
+  case kDevicePrimary:
+    if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_POWERDOWN) == -1) {
+      IOCTL_LOGE(FB_BLANK_POWERDOWN, hw_context->type);
+      return kErrorHardware;
+    }
+    break;
+  case kDeviceHDMI:
+    {
+      hw_context->ResetMDPCommit();
+      mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
+      mdp_commit.input_layer_cnt = 0;
+      mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+      if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
+        IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
+        return kErrorHardware;
+      }
+    }
+    break;
+  case kDeviceVirtual:
+  default:
+    break;
   }
 
   return kErrorNone;
@@ -513,6 +532,15 @@
       if (error != kErrorNone) {
         return error;
       }
+
+      if (layer.transform.flip_vertical) {
+        mdp_layer.flags |= MDP_LAYER_FLIP_UD;
+      }
+
+      if (layer.transform.flip_horizontal) {
+        mdp_layer.flags |= MDP_LAYER_FLIP_LR;
+      }
+
       mdp_layer_count++;
     }
   }
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index 7827af2..771c07f 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -369,6 +369,8 @@
     return -EINVAL;
   }
 
+  int status = 0;
+
   size_t num_hw_layers = content_list->numHwLayers;
   if (num_hw_layers <= 1) {
     if (!num_hw_layers) {
@@ -401,7 +403,7 @@
   DisplayError error = display_intf_->Commit(&layer_stack_);
   if (UNLIKELY(error != kErrorNone)) {
     DLOGE("Commit failed. Error = %d", error);
-    return -EINVAL;
+    status = -EINVAL;
   }
 
   for (size_t i = 0; i < num_hw_layers; i++) {
@@ -409,7 +411,8 @@
     Layer &layer = layer_stack_.layers[i];
     LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
 
-    if (layer.composition == kCompositionSDE || layer.composition == kCompositionGPUTarget) {
+    if ((status == 0) && (layer.composition == kCompositionSDE ||
+                         layer.composition == kCompositionGPUTarget)) {
       hwc_layer.releaseFenceFd = layer_buffer->release_fence_fd;
     }
 
@@ -418,7 +421,7 @@
     }
   }
 
-  return 0;
+  return status;
 }
 
 bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) {
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index a5bf0b5..7e7b44b 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
  * Not a Contribution, Apache license notifications and license are retained
  * for attribution purposes only.
  *
@@ -19,6 +19,7 @@
 #include <math.h>
 #include "hwc_mdpcomp.h"
 #include <sys/ioctl.h>
+#include <dlfcn.h>
 #include "hdmi.h"
 #include "qdMetaData.h"
 #include "mdp_version.h"
@@ -50,6 +51,12 @@
 int MDPComp::sMaxSecLayers = 1;
 bool MDPComp::enablePartialUpdateForMDP3 = false;
 bool MDPComp::sIsPartialUpdateActive = true;
+void *MDPComp::sLibPerfHint = NULL;
+int MDPComp::sPerfLockHandle = 0;
+int (*MDPComp::sPerfLockAcquire)(int, int, int*, int) = NULL;
+int (*MDPComp::sPerfLockRelease)(int value) = NULL;
+int MDPComp::sPerfHintWindow = -1;
+
 MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
     if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
         sSrcSplitEnabled = true;
@@ -194,6 +201,14 @@
 
     sIsPartialUpdateActive = getPartialUpdatePref(ctx);
 
+    if(property_get("persist.mdpcomp_perfhint", property, "-1") > 0) {
+        int val = atoi(property);
+        if(val > 0 && loadPerfLib()) {
+            sPerfHintWindow = val;
+            ALOGI("PerfHintWindow = %d", sPerfHintWindow);
+        }
+    }
+
     return true;
 }
 
@@ -1325,6 +1340,11 @@
 
     if(!postHeuristicsHandling(ctx, list)) {
         ALOGD_IF(isDebug(), "post heuristic handling failed");
+        if(errno == ENOBUFS) {
+            ALOGD_IF(isDebug(), "SMP Allocation failed");
+            //On SMP allocation failure in video only comp add padding round
+            ctx->isPaddingRound = true;
+        }
         reset(ctx);
         return false;
     }
@@ -1372,6 +1392,12 @@
        }
     }
 
+    /* Bail out if we dont have any secure RGB layers */
+    if (!ctx->listStats[mDpy].secureRGBCount) {
+        reset(ctx);
+        return false;
+    }
+
     mCurrentFrame.reset(numAppLayers);
     mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
 
@@ -1895,25 +1921,38 @@
     return true;
 }
 
+// Checks only if videos or single layer(RGB) is updating
+// which is used for setting dynamic fps or perf hint for single
+// layer video playback
+bool MDPComp::onlyVideosUpdating(hwc_context_t *ctx,
+                                hwc_display_contents_1_t* list) {
+    bool support = false;
+    FrameInfo frame;
+    frame.reset(mCurrentFrame.layerCount);
+    memset(&frame.drop, 0, sizeof(frame.drop));
+    frame.dropCount = 0;
+    ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo", __FUNCTION__);
+    updateLayerCache(ctx, list, frame);
+    updateYUV(ctx, list, false /*secure only*/, frame);
+    // There are only updating YUV layers or there is single RGB
+    // Layer(Youtube)
+    if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
+                                        (frame.layerCount == 1)) {
+        support = true;
+    }
+    return support;
+}
+
 void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
     //For primary display, set the dynamic refreshrate
     if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
                                         ctx->mUseMetaDataRefreshRate) {
-        FrameInfo frame;
-        frame.reset(mCurrentFrame.layerCount);
-        memset(&frame.drop, 0, sizeof(frame.drop));
-        frame.dropCount = 0;
-        ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo for Dyn Refresh Rate",
-                 __FUNCTION__);
-        updateLayerCache(ctx, list, frame);
-        updateYUV(ctx, list, false /*secure only*/, frame);
         uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
         MDPVersion& mdpHw = MDPVersion::getInstance();
         if(sIdleFallBack) {
             //Set minimum panel refresh rate during idle timeout
             refreshRate = mdpHw.getMinFpsSupported();
-        } else if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
-                                (frame.layerCount == 1)) {
+        } else if(onlyVideosUpdating(ctx, list)) {
             //Set the new fresh rate, if there is only one updating YUV layer
             //or there is one single RGB layer with this request
             refreshRate = ctx->listStats[mDpy].refreshRateRequest;
@@ -2031,6 +2070,7 @@
 #ifdef DYNAMIC_FPS
     setDynRefreshRate(ctx, list);
 #endif
+    setPerfHint(ctx, list);
 
     mCachedFrame.cacheAll(list);
     mCachedFrame.updateCounts(mCurrentFrame);
@@ -2817,5 +2857,66 @@
     sIsPartialUpdateActive = enable;
     return 0;
 }
+
+bool MDPComp::loadPerfLib() {
+    char perfLibPath[PROPERTY_VALUE_MAX] = {0};
+    bool success = false;
+    if((property_get("ro.vendor.extension_library", perfLibPath, NULL) <= 0)) {
+        ALOGE("vendor library not set in ro.vendor.extension_library");
+        return false;
+    }
+
+    sLibPerfHint = dlopen(perfLibPath, RTLD_NOW);
+    if(sLibPerfHint) {
+        *(void **)&sPerfLockAcquire = dlsym(sLibPerfHint, "perf_lock_acq");
+        *(void **)&sPerfLockRelease = dlsym(sLibPerfHint, "perf_lock_rel");
+        if (!sPerfLockAcquire || !sPerfLockRelease) {
+            ALOGE("Failed to load symbols for perfLock");
+            dlclose(sLibPerfHint);
+            sLibPerfHint = NULL;
+            return false;
+        }
+        success = true;
+        ALOGI("Successfully Loaded perf hint API's");
+    } else {
+        ALOGE("Failed to open %s : %s", perfLibPath, dlerror());
+    }
+    return success;
+}
+
+void MDPComp::setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+    if ((sPerfHintWindow < 0) || mDpy || !sLibPerfHint) {
+        return;
+    }
+    static int count = sPerfHintWindow;
+    static int perflockFlag = 0;
+
+    /* Send hint to mpctl when single layer is updated
+     * for a successful number of windows. Hint release
+     * happens immediately upon multiple layer update.
+     */
+    if (onlyVideosUpdating(ctx, list)) {
+        if(count) {
+            count--;
+        }
+    } else {
+        if (perflockFlag) {
+            perflockFlag = 0;
+            sPerfLockRelease(sPerfLockHandle);
+        }
+        count = sPerfHintWindow;
+    }
+    if (count == 0 && !perflockFlag) {
+        int perfHint = 0x4501; // 45-display layer hint, 01-Enable
+        sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
+                                    &perfHint, sizeof(perfHint)/sizeof(int));
+        if(sPerfLockHandle < 0) {
+            ALOGE("Perf Lock Acquire Failed");
+        } else {
+            perflockFlag = 1;
+        }
+    }
+}
+
 }; //namespace
 
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 4978182..302b047 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -247,6 +247,10 @@
             hwc_display_contents_1_t* list);
     /* checks for conditions to enable partial udpate */
     bool canPartialUpdate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    // Checks if only videocontent is updating
+    bool onlyVideosUpdating(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    static bool loadPerfLib();
+    void setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list);
 
     int mDpy;
     static bool sEnabled;
@@ -269,6 +273,12 @@
     bool allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index);
     //Enable Partial Update for MDP3 targets
     static bool enablePartialUpdateForMDP3;
+    static void *sLibPerfHint;
+    static int sPerfLockHandle;
+    static int (*sPerfLockAcquire)(int, int, int*, int);
+    static int (*sPerfLockRelease)(int value);
+    static int sPerfHintWindow;
+
 };
 
 class MDPCompNonSplit : public MDPComp {
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index b772a6e..dd030ef 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -280,10 +280,11 @@
     if(src_w > (int) mdpHw.getMaxPipeWidth()) {
         //If the client sends us something > what a layer mixer supports
         //then it means it doesn't want to use split-pipe but wants us to
-        //decimate. A minimum decimation of 2 will ensure that the width is
+        //decimate. A minimum decimation of 1 will ensure that the width is
         //always within layer mixer limits.
-        if(horzDeci < 2)
-            horzDeci = 2;
+        const uint8_t minDeci = 1;
+        if(horzDeci < minDeci)
+            horzDeci = minDeci;
     }
 }