Merge "hwc: Reserve pipes for video layers first"
diff --git a/displayengine/include/utils/constants.h b/displayengine/include/utils/constants.h
index 8630d45..5dfcc59 100644
--- a/displayengine/include/utils/constants.h
+++ b/displayengine/include/utils/constants.h
@@ -59,6 +59,8 @@
 
 #define IDLE_TIMEOUT_DEFAULT_MS 70
 
+#define IS_RGB_FORMAT(format) (((format) < kFormatYCbCr420Planar) ? true: false)
+
 template <class T>
 inline void Swap(T &a, T &b) {
   T c(a);
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index b4aa779..ea90dfb 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -33,6 +33,15 @@
 
 namespace sde {
 
+static void GetAlignFactor(const LayerBufferFormat &format, uint32_t *align_x, uint32_t *align_y) {
+  *align_x = 1;
+  *align_y = 1;
+  if (!IS_RGB_FORMAT(format)) {
+    *align_x = 2;
+    *align_y = 2;
+  }
+}
+
 void ResManager::RotationConfig(LayerBufferFormat format, const LayerTransform &transform,
                                 const float &downscale, LayerRect *src_rect,
                                 struct HWLayerConfig *layer_config, uint32_t *rotate_count) {
@@ -46,22 +55,24 @@
   dst_rect.left = 0.0f;
 
   rotate->downscale_ratio = downscale;
+  uint32_t align_x, align_y;
+  GetAlignFactor(format, &align_x, &align_y);
 
   // downscale when doing rotation
   if (rot90) {
     if (downscale > 1.0f) {
-      src_height = ROUND_UP_ALIGN_DOWN(src_height, downscale);
+      src_height = ROUND_UP_ALIGN_DOWN(src_height, downscale * FLOAT(align_x));
       src_rect->bottom = src_rect->top + src_height;
-      src_width = ROUND_UP_ALIGN_DOWN(src_width, downscale);
+      src_width = ROUND_UP_ALIGN_DOWN(src_width, downscale * FLOAT(align_y));
       src_rect->right = src_rect->left + src_width;
     }
     dst_rect.right = src_height / downscale;
     dst_rect.bottom = src_width / downscale;
   } else {
     if (downscale > 1.0f) {
-      src_width = ROUND_UP_ALIGN_DOWN(src_width, downscale);
+      src_width = ROUND_UP_ALIGN_DOWN(src_width, downscale * FLOAT(align_x));
       src_rect->right = src_rect->left + src_width;
-      src_height = ROUND_UP_ALIGN_DOWN(src_height, downscale);
+      src_height = ROUND_UP_ALIGN_DOWN(src_height, downscale * FLOAT(align_y));
       src_rect->bottom = src_rect->top + src_height;
     }
     dst_rect.right = src_width / downscale;
@@ -250,11 +261,9 @@
       continue;
     }
 
-    uint32_t align_x = 1, align_y = 1;
-    if (IsYuvFormat(layer.input_buffer->format)) {
-      // TODO(user) Select x and y alignment according to the format
-      align_x = 2;
-      align_y = 2;
+    uint32_t align_x, align_y;
+    GetAlignFactor(layer.input_buffer->format, &align_x, &align_y);
+    if (align_x > 1 || align_y > 1) {
       NormalizeRect(align_x, align_y, &src_rect);
     }
 
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 238dfa8..262d7e1 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -325,8 +325,7 @@
 
     HWPipeInfo *pipe_info = &layer_config.left_pipe;
 
-    // Should have a generic macro
-    bool is_yuv = IsYuvFormat(layer.input_buffer->format);
+    bool is_yuv = !IS_RGB_FORMAT(layer.input_buffer->format);
 
     // left pipe is needed
     if (pipe_info->valid) {
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index b2ddcb9..7f78b29 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -194,7 +194,6 @@
                  LayerRect *src_left, LayerRect *dst_left, LayerRect *src_right,
                  LayerRect *dst_right, uint32_t align_x);
   bool IsMacroTileFormat(const LayerBuffer *buffer) { return buffer->flags.macro_tile; }
-  bool IsYuvFormat(LayerBufferFormat format) { return (format >= kFormatYCbCr420Planar); }
   bool IsRotationNeeded(float rotation)
          { return (UINT32(rotation) == 90 || UINT32(rotation) == 270); }
   void RotationConfig(LayerBufferFormat format, const LayerTransform &transform,
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index 1be682d..4160054 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -105,10 +105,12 @@
     break;
   case HWC_POWER_MODE_NORMAL:
     state = kStateOn;
+    last_power_mode_ = HWC_POWER_MODE_NORMAL;
     break;
   case HWC_POWER_MODE_DOZE:
   case HWC_POWER_MODE_DOZE_SUSPEND:
     state = kStateDoze;
+    last_power_mode_ = HWC_POWER_MODE_DOZE;
     break;
   default:
     return -EINVAL;
@@ -208,6 +210,10 @@
   DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
 }
 
+uint32_t HWCDisplay::GetLastPowerMode() {
+  return last_power_mode_;
+}
+
 DisplayError HWCDisplay::VSync(const DisplayEventVSync &vsync) {
   if (*hwc_procs_) {
     (*hwc_procs_)->vsync(*hwc_procs_, id_, vsync.timestamp);
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index 8feddf6..7ef8187 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -46,6 +46,7 @@
   virtual int SetActiveConfig(hwc_display_contents_1_t *content_list);
   virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+  virtual uint32_t GetLastPowerMode();
 
  protected:
   // Maximum number of layers supported by display engine.
@@ -117,6 +118,7 @@
   uint32_t dump_frame_count_;
   uint32_t dump_frame_index_;
   bool dump_input_layers_;
+  uint32_t last_power_mode_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index b6d0c18..4498f18 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -44,6 +44,9 @@
 
 #define __CLASS__ "HWCSession"
 
+#define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
+#define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0"
+
 static sde::HWCSession::HWCModuleMethods g_hwc_module_methods;
 
 hwc_module_t HAL_MODULE_INFO_SYM = {
@@ -63,10 +66,11 @@
 namespace sde {
 
 Locker HWCSession::locker_;
+bool HWCSession::reset_panel_ = false;
 
 HWCSession::HWCSession(const hw_module_t *module) : core_intf_(NULL), hwc_procs_(NULL),
             display_primary_(NULL), display_external_(NULL), display_virtual_(NULL),
-            hotplug_thread_exit_(false), hotplug_thread_name_("HWC_HotPlugThread") {
+            uevent_thread_exit_(false), uevent_thread_name_("HWC_UeventThread") {
   hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
   hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_4;
   hwc_composer_device_1_t::common.module = const_cast<hw_module_t*>(module);
@@ -141,8 +145,8 @@
     return status;
   }
 
-  if (pthread_create(&hotplug_thread_, NULL, &HWCHotPlugThread, this) < 0) {
-    DLOGE("Failed to start = %s, error = %s HDMI display Not supported", hotplug_thread_name_);
+  if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) {
+    DLOGE("Failed to start = %s, error = %s", uevent_thread_name_);
     display_primary_->Deinit();
     delete display_primary_;
     CoreInterface::DestroyCore();
@@ -156,8 +160,8 @@
   display_primary_->SetPowerMode(HWC_POWER_MODE_OFF);
   display_primary_->Deinit();
   delete display_primary_;
-  hotplug_thread_exit_ = true;
-  pthread_join(hotplug_thread_, NULL);
+  uevent_thread_exit_ = true;
+  pthread_join(uevent_thread_, NULL);
 
   DisplayError error = CoreInterface::DestroyCore();
   if (error != kErrorNone) {
@@ -218,6 +222,11 @@
 
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
 
+  if (reset_panel_) {
+    DLOGW("panel is in bad state, resetting the panel");
+    hwc_session->ResetPanel();
+  }
+
   for (ssize_t i = (num_displays-1); i >= 0; i--) {
     hwc_display_contents_1_t *content_list = displays[i];
 
@@ -690,18 +699,18 @@
   }
 }
 
-void* HWCSession::HWCHotPlugThread(void *context) {
+void* HWCSession::HWCUeventThread(void *context) {
   if (context) {
-    return reinterpret_cast<HWCSession *>(context)->HWCHotPlugThreadHandler();
+    return reinterpret_cast<HWCSession *>(context)->HWCUeventThreadHandler();
   }
 
   return NULL;
 }
 
-void* HWCSession::HWCHotPlugThreadHandler() {
+void* HWCSession::HWCUeventThreadHandler() {
   static char uevent_data[PAGE_SIZE];
   int length = 0;
-  prctl(PR_SET_NAME, hotplug_thread_name_, 0, 0, 0);
+  prctl(PR_SET_NAME, uevent_thread_name_, 0, 0, 0);
   setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
   if (!uevent_init()) {
     DLOGE("Failed to init uevent");
@@ -709,19 +718,28 @@
     return NULL;
   }
 
-  while (!hotplug_thread_exit_) {
+  while (!uevent_thread_exit_) {
     // keep last 2 zeroes to ensure double 0 termination
     length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
 
-    if (!strcasestr("change@/devices/virtual/switch/hdmi", uevent_data)) {
-      continue;
-    }
-    DLOGI("Uevent HDMI = %s", uevent_data);
-    int connected = GetHDMIConnectedState(uevent_data, length);
-    if (connected >= 0) {
-      DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
-      if (HotPlugHandler(connected) == -1) {
-        DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
+    if (strcasestr(HWC_UEVENT_SWITCH_HDMI, uevent_data)) {
+      DLOGI("Uevent HDMI = %s", uevent_data);
+      int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
+      if (connected >= 0) {
+        DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
+        if (HotPlugHandler(connected) == -1) {
+          DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
+        }
+      }
+    } else if (strcasestr(HWC_UEVENT_GRAPHICS_FB0, uevent_data)) {
+      DLOGI("Uevent FB0 = %s", uevent_data);
+      int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
+      if (panel_reset == 0) {
+        if (hwc_procs_) {
+          reset_panel_ = true;
+          hwc_procs_->invalidate(hwc_procs_);
+        } else
+          DLOGW("Ignore resetpanel - hwc_proc not registered");
       }
     }
   }
@@ -730,18 +748,43 @@
   return NULL;
 }
 
-int HWCSession::GetHDMIConnectedState(const char *uevent_data, int length) {
-  const char* iterator_str = uevent_data;
+int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
+  const char *iterator_str = uevent_data;
   while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
-    char* pstr = strstr(iterator_str, "SWITCH_STATE=");
+    char *pstr = strstr(iterator_str, event_info);
     if (pstr != NULL) {
-      return (atoi(iterator_str + strlen("SWITCH_STATE=")));
+      return (atoi(iterator_str + strlen(event_info)));
     }
     iterator_str += strlen(iterator_str) + 1;
   }
+
   return -1;
 }
 
+void HWCSession::ResetPanel() {
+  int status = -EINVAL;
+
+  DLOGI("Powering off primary");
+  status = display_primary_->SetPowerMode(HWC_POWER_MODE_OFF);
+  if (status) {
+    DLOGE("power-off on primary failed with error = %d",status);
+  }
+
+  DLOGI("Restoring power mode on primary");
+  uint32_t mode = display_primary_->GetLastPowerMode();
+  status = display_primary_->SetPowerMode(mode);
+  if (status) {
+    DLOGE("Setting power mode = %d on primary failed with error = %d", mode,status);
+  }
+
+  status = display_primary_->EventControl(HWC_EVENT_VSYNC, 1);
+  if (status) {
+    DLOGE("enabling vsync failed for primary with error = %d",status);
+  }
+
+  reset_panel_ = false;
+}
+
 int HWCSession::HotPlugHandler(bool connected) {
   if (!hwc_procs_) {
      DLOGW("Ignore hotplug - hwc_proc not registered");
diff --git a/displayengine/libs/hwc/hwc_session.h b/displayengine/libs/hwc/hwc_session.h
index 1608ce5..3c5cc7f 100644
--- a/displayengine/libs/hwc/hwc_session.h
+++ b/displayengine/libs/hwc/hwc_session.h
@@ -68,11 +68,12 @@
   static int GetActiveConfig(hwc_composer_device_1 *device, int disp);
   static int SetActiveConfig(hwc_composer_device_1 *device, int disp, int index);
 
-  // Hotplug thread for HDMI connect/disconnect
-  static void* HWCHotPlugThread(void *context);
-  void* HWCHotPlugThreadHandler();
-  int GetHDMIConnectedState(const char *uevent_data, int length);
+  // Uevent thread
+  static void* HWCUeventThread(void *context);
+  void* HWCUeventThreadHandler();
+  int GetEventValue(const char *uevent_data, int length, const char *event_info);
   int HotPlugHandler(bool connected);
+  void ResetPanel();
   bool ValidateContentList(hwc_display_contents_1_t *content_list);
   int CreateVirtualDisplay(HWCSession *hwc_session, hwc_display_contents_1_t *content_list);
   int DestroyVirtualDisplay(HWCSession *hwc_session);
@@ -93,9 +94,10 @@
   HWCDisplayPrimary *display_primary_;
   HWCDisplayExternal *display_external_;
   HWCDisplayVirtual *display_virtual_;
-  pthread_t hotplug_thread_;
-  bool hotplug_thread_exit_;
-  const char *hotplug_thread_name_;
+  pthread_t uevent_thread_;
+  bool uevent_thread_exit_;
+  static bool reset_panel_;
+  const char *uevent_thread_name_;
   HWCBufferAllocator *buffer_allocator_;
   HWCBufferSyncHandler *buffer_sync_handler_;
 };
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index c344045..5be5d00 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -8,6 +8,13 @@
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes) \
                                  $(TOP)/external/skia/include/core \
                                  $(TOP)/external/skia/include/images
+
+ifeq ($(strip $(TARGET_USES_QCOM_DISPLAY_PP)),true)
+LOCAL_C_INCLUDES              += $(TARGET_OUT_HEADERS)/qdcm/inc \
+                                 $(TARGET_OUT_HEADERS)/common/inc \
+                                 $(TARGET_OUT_HEADERS)/pp/inc
+endif
+
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libEGL liboverlay \
                                  libhdmi libqdutils libhardware_legacy \
                                  libdl libmemalloc libqservice libsync \
@@ -38,4 +45,18 @@
                                  hwc_dump_layers.cpp \
                                  hwc_ad.cpp \
                                  hwc_virtual.cpp
+
+TARGET_MIGRATE_QDCM_LIST := msm8909
+TARGET_MIGRATE_QDCM := $(call is-board-platform-in-list,$(TARGET_MIGRATE_QDCM_LIST))
+
+ifeq ($(TARGET_MIGRATE_QDCM), true)
+ifeq ($(strip $(TARGET_USES_QCOM_DISPLAY_PP)),true)
+LOCAL_SRC_FILES += hwc_qdcm.cpp
+else
+LOCAL_SRC_FILES += hwc_qdcm_legacy.cpp
+endif
+else
+LOCAL_SRC_FILES += hwc_qdcm_legacy.cpp
+endif
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 85e5d1b..6acb663 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -39,9 +39,11 @@
 #include "hwc_ad.h"
 #include "profiler.h"
 #include "hwc_virtual.h"
+#include "hwc_qdcm.h"
 
 using namespace qhwc;
 using namespace overlay;
+using namespace qQdcm;
 
 #define VSYNC_DEBUG 0
 #define POWER_MODE_DEBUG 1
@@ -278,6 +280,7 @@
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     const int dpy = HWC_DISPLAY_PRIMARY;
     bool fbComp = false;
+
     if (!ctx->mBootAnimCompleted)
         processBootAnimCompleted(ctx);
     if (LIKELY(list && list->numHwLayers > 1) && ctx->dpyAttr[dpy].connected &&
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index 34de2e6..f18ad36 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -37,6 +37,7 @@
 #include <display_config.h>
 #include <hdmi.h>
 #include <video/msm_hdmi_modes.h>
+#include <hwc_qdcm.h>
 
 #define QCLIENT_DEBUG 0
 
@@ -45,6 +46,7 @@
 using namespace qhwc;
 using namespace overlay;
 using namespace qdutils;
+using namespace qQdcm;
 
 namespace qClient {
 
@@ -554,6 +556,8 @@
         case IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
             ret = getDisplayAttributesForConfig(mHwcContext, inParcel,
                     outParcel);
+        case IQService::QDCM_SVC_CMDS:
+            qdcmCmdsHandler(mHwcContext, inParcel, outParcel);
             break;
         default:
             ret = NO_ERROR;
diff --git a/libhwcomposer/hwc_qdcm.cpp b/libhwcomposer/hwc_qdcm.cpp
new file mode 100644
index 0000000..9821e4e
--- /dev/null
+++ b/libhwcomposer/hwc_qdcm.cpp
@@ -0,0 +1,292 @@
+/*
+ *  Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <hwc_qdcm.h>
+#include <hwc_utils.h>
+#include <utils/String16.h>
+#include <mdp_version.h>
+#include "mode_manager.h"
+#include "libmm-disp-apis.h"
+#include "IQService.h"
+
+using namespace android;
+using namespace qService;
+using namespace qhwc;
+using namespace qmode;
+
+namespace qQdcm {
+//----------------------------------------------------------------------------
+void qdcmInitContext(hwc_context_t *ctx)
+{
+    loadQdcmLibrary(ctx);
+}
+
+void qdcmCloseContext(hwc_context_t *ctx)
+{
+    if (ctx->mQdcmInfo.mQdcmMode) {
+        unloadQdcmLibrary(ctx);
+    }
+}
+
+void qdcmApplyDefaultAfterBootAnimationDone(hwc_context_t *ctx)
+{
+    if (ctx->mQdcmInfo.mQdcmMode)
+        ctx->mQdcmInfo.mQdcmMode->applyDefaultMode(0);
+}
+
+static void qdcmSetActiveMode(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        struct SET_MODE_PROP_IN params =
+                           { (disp_id_type)in->readInt32(), in->readInt32()};
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_ACTIVE_MODE,
+                (void *)&params, (void *)NULL);
+
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmSetDefaultMode(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        struct SET_MODE_PROP_IN params =
+                          { (disp_id_type)in->readInt32(), in->readInt32()};
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_DEFAULT_MODE,
+                (void *)&params, (void *)NULL);
+
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmGetDefaultMode(hwc_context_t *ctx,
+                                            const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        int params = in->readInt32();
+        int modeid = 0;
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_DEFAULT_MODE,
+                (const void *)&params, (void *)&modeid);
+
+        out->writeInt32(modeid);
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmGetColorBalanceRange(hwc_context_t *ctx __unused,
+                const Parcel *in __unused, Parcel *out __unused)
+{
+}
+
+static void qdcmGetColorBalance(hwc_context_t *ctx,
+                                            const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        int params = in->readInt32();
+        int warmness = 0;
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_CB,
+                (const void *)&params, (void *)&warmness);
+
+        out->writeInt32(warmness);
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmSetColorBalance(hwc_context_t *ctx,
+                                            const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        struct SET_CB_IN params =
+                           { (disp_id_type)in->readInt32(), in->readInt32() };
+
+        ALOGD_IF(QDCM_DEBUG, "%s dispID = %d, warmness = %d\n",
+                __FUNCTION__, params.id, params.warmness);
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_CB,
+                (const void *)&params, NULL);
+
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmSaveModeV2(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        struct SAVE_DISPLAY_MODE_V2_IN params =
+                     { (disp_id_type)in->readInt32(),
+                                     in->readCString(),
+                           (uint32_t)in->readInt32(),
+                                     in->readInt32()
+                     };
+        int value = 0;
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SAVE_MODE_V2,
+                (const void *)&params, (void *)&value);
+
+        out->writeInt32(value);
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmSetPaConfig(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        struct SET_PA_CONFIG_IN params;
+
+        params.id = (disp_id_type)in->readInt32();
+        params.pa.ops = in->readInt32();
+        params.pa.data.hue = in->readInt32();
+        params.pa.data.saturation = in->readInt32();
+        params.pa.data.value = in->readInt32();
+        params.pa.data.contrast = in->readInt32();
+        params.pa.data.sat_thresh = in->readInt32();
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_PA_CONFIG,
+                (const void *)&params, NULL);
+
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmGetPaConfig(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        int params = in->readInt32();
+        struct disp_pa_config value;
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_PA_CONFIG,
+                (const void *)&params, (void *)&value);
+
+        out->writeInt32(value.ops);
+        out->writeInt32(value.data.hue);
+        out->writeInt32(value.data.saturation);
+        out->writeInt32(value.data.value);
+        out->writeInt32(value.data.contrast);
+        out->writeInt32(value.data.sat_thresh);
+
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmGetPaRange(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        int params = in->readInt32();
+        struct disp_pa_range value;
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_PA_RANGE,
+                (const void *)&params, (void *)&value);
+
+        out->writeInt32(value.max.hue);
+        out->writeInt32(value.max.saturation);
+        out->writeInt32(value.max.value);
+        out->writeInt32(value.max.contrast);
+        out->writeInt32(value.max.sat_thresh);
+        out->writeInt32(value.min.hue);
+        out->writeInt32(value.min.saturation);
+        out->writeInt32(value.min.value);
+        out->writeInt32(value.min.contrast);
+        out->writeInt32(value.min.sat_thresh);
+
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+void qdcmCmdsHandler(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+    int subcmd = in->readInt32();
+
+    ALOGD_IF(QDCM_DEBUG, "%s enter subcmd = %d\n", __FUNCTION__, subcmd);
+    switch (subcmd) {
+        case CMD_SET_ACTIVE_MODE:
+            qdcmSetActiveMode(ctx, in, out);
+            break;
+        case CMD_SET_DEFAULT_MODE:
+            qdcmSetDefaultMode(ctx, in, out);
+            break;
+        case CMD_GET_DEFAULT_MODE:
+            qdcmGetDefaultMode(ctx, in, out);
+            break;
+        case CMD_GET_CB_RANGE:
+            qdcmGetColorBalanceRange(ctx, in, out);
+            break;
+        case CMD_GET_CB:
+            qdcmGetColorBalance(ctx, in, out);
+            break;
+        case CMD_SET_CB:
+            qdcmSetColorBalance(ctx, in, out);
+            break;
+        case CMD_SAVE_MODE_V2:
+            qdcmSaveModeV2(ctx, in, out);
+            break;
+        case CMD_SET_PA_CONFIG:
+            qdcmSetPaConfig(ctx, in, out);
+            break;
+        case CMD_GET_PA_CONFIG:
+            qdcmGetPaConfig(ctx, in, out);
+            break;
+        case CMD_GET_PA_RANGE:
+            qdcmGetPaRange(ctx, in, out);
+            break;
+    }
+}
+
+
+} //namespace qQdcm
+
diff --git a/libhwcomposer/hwc_qdcm.h b/libhwcomposer/hwc_qdcm.h
new file mode 100644
index 0000000..6453159
--- /dev/null
+++ b/libhwcomposer/hwc_qdcm.h
@@ -0,0 +1,94 @@
+/*
+ *  Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_QDCM_H
+#define ANDROID_QDCM_H
+
+#include <utils/Errors.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+#include <hwc_utils.h>
+#include <dlfcn.h>
+#include <binder/Parcel.h>
+#include <cutils/properties.h>
+
+#define QDCM_DEBUG 0
+
+namespace qmode {
+class ModeManager;
+}
+
+using namespace android;
+
+namespace qQdcm {
+// ----------------------------------------------------------------------------
+
+//function prototypes used for QDCM library and service
+static inline void loadQdcmLibrary(hwc_context_t *ctx)
+{
+    ctx->mQdcmInfo.mQdcmLib = dlopen("libmm-qdcm.so", RTLD_NOW);
+    qmode::ModeManager* (*factory)() = NULL;
+
+    if (ctx->mQdcmInfo.mQdcmLib)
+        *(void **)&factory = dlsym(ctx->mQdcmInfo.mQdcmLib, "getObject");
+
+    if (factory) {
+        ctx->mQdcmInfo.mQdcmMode = factory();
+    } else {
+        ctx->mQdcmInfo.mQdcmMode = NULL;
+        ALOGE("QDCM LIbrary load failing!");
+    }
+
+    ALOGD_IF(QDCM_DEBUG, "QDCM LIbrary loaded successfully!");
+}
+
+static inline void unloadQdcmLibrary(hwc_context_t *ctx)
+{
+    void (*destroy)(qmode::ModeManager*) = NULL;
+
+    if (ctx->mQdcmInfo.mQdcmLib) {
+        *(void **)&destroy = dlsym(ctx->mQdcmInfo.mQdcmLib, "deleteObject");
+
+        if (destroy) {
+            destroy(ctx->mQdcmInfo.mQdcmMode);
+            ctx->mQdcmInfo.mQdcmMode = NULL;
+        }
+
+        dlclose(ctx->mQdcmInfo.mQdcmLib);
+        ctx->mQdcmInfo.mQdcmLib = NULL;
+    }
+}
+
+void qdcmInitContext(hwc_context_t *);
+void qdcmCloseContext(hwc_context_t *);
+void qdcmApplyDefaultAfterBootAnimationDone(hwc_context_t *);
+void qdcmCmdsHandler(hwc_context_t*, const Parcel*, Parcel*);
+
+}; // namespace qQdcm
+#endif // ANDROID_QDCM_H
diff --git a/libhwcomposer/hwc_qdcm_legacy.cpp b/libhwcomposer/hwc_qdcm_legacy.cpp
new file mode 100644
index 0000000..9c2c7b0
--- /dev/null
+++ b/libhwcomposer/hwc_qdcm_legacy.cpp
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <hwc_qdcm.h>
+#include <hwc_utils.h>
+#include <IQService.h>
+#include <mdp_version.h>
+#include <dlfcn.h>
+
+using namespace android;
+using namespace qService;
+using namespace qhwc;
+
+namespace qQdcm {
+//----------------------------------------------------------------------------
+void qdcmInitContext(hwc_context_t *ctx)
+{
+}
+
+void qdcmCloseContext(hwc_context_t *ctx)
+{
+}
+
+void qdcmApplyDefaultAfterBootAnimationDone(hwc_context_t *ctx)
+{
+    int ret = 0;
+    int (*applyMode)(int) = NULL;
+    void *modeHandle = NULL;
+
+    modeHandle = dlopen("libmm-qdcm.so", RTLD_NOW);
+    if (modeHandle) {
+        *(void **)&applyMode = dlsym(modeHandle, "applyDefaults");
+        if (applyMode) {
+            ret = applyMode(HWC_DISPLAY_PRIMARY);
+            if (ret)
+                ALOGE("%s: Not able to apply default mode", __FUNCTION__);
+        } else {
+            ALOGE("%s: No symbol applyDefaults found", __FUNCTION__);
+        }
+        dlclose(modeHandle);
+    } else {
+        ALOGE("%s: Not able to load libmm-qdcm.so", __FUNCTION__);
+    }
+}
+
+//do nothing in case qdcm legacy implementation.
+void qdcmCmdsHandler(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+}
+
+
+} //namespace qQdcm
+
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index a3cb196..db982db 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -43,6 +43,7 @@
 #include "comptype.h"
 #include "hwc_virtual.h"
 #include "qd_utils.h"
+#include "hwc_qdcm.h"
 #include <sys/sysinfo.h>
 #include <dlfcn.h>
 #include <video/msm_hdmi_modes.h>
@@ -52,6 +53,7 @@
 using namespace android;
 using namespace overlay;
 using namespace overlay::utils;
+using namespace qQdcm;
 namespace ovutils = overlay::utils;
 
 #ifdef QCOM_BSP
@@ -477,6 +479,10 @@
 
     memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
     ctx->mHPDEnabled = false;
+
+    //init qdcm service related context.
+    qdcmInitContext(ctx);
+
     ALOGI("Initializing Qualcomm Hardware Composer");
     ALOGI("MDP version: %d", ctx->mMDP.version);
 
@@ -490,6 +496,9 @@
 
 void closeContext(hwc_context_t *ctx)
 {
+    //close qdcm service related context.
+    qdcmCloseContext(ctx);
+
     if(ctx->mOverlay) {
         delete ctx->mOverlay;
         ctx->mOverlay = NULL;
@@ -2701,29 +2710,16 @@
 void processBootAnimCompleted(hwc_context_t *ctx) {
     char value[PROPERTY_VALUE_MAX];
     int ret = -1;
-    int (*applyMode)(int) = NULL;
-    void *modeHandle = NULL;
 
     // Applying default mode after bootanimation is finished
     property_get("init.svc.bootanim", value, "running");
 
     if (!strncmp(value,"stopped",strlen("stopped"))) {
-        modeHandle = dlopen("libmm-qdcm.so", RTLD_NOW);
-        if (modeHandle) {
-            *(void **)&applyMode = dlsym(modeHandle, "applyDefaults");
-            if (applyMode) {
-                ret = applyMode(HWC_DISPLAY_PRIMARY);
-                if (ret)
-                    ALOGD("%s: Not able to apply default mode", __FUNCTION__);
-            } else {
-                ALOGE("%s: No symbol applyDefaults found", __FUNCTION__);
-            }
-            dlclose(modeHandle);
-        } else {
-            ALOGE("%s: Not able to load libmm-qdcm.so", __FUNCTION__);
-        }
-
         ctx->mBootAnimCompleted = true;
+
+        //one-shot action check if bootanimation completed then apply
+        //default display mode.
+        qdcmApplyDefaultAfterBootAnimationDone(ctx);
     }
 }
 
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index af43514..ac61e68 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -55,6 +55,10 @@
 
 namespace ovutils = overlay::utils;
 
+namespace qmode {
+class ModeManager;
+}
+
 namespace overlay {
 class Overlay;
 class Rotator;
@@ -611,6 +615,13 @@
     EGLDisplay mEGLDisplay;
 };
 
+//struct holds the information about libmm-qdcm.so
+struct qdcm_info {
+    qmode::ModeManager *mQdcmMode;
+    void *mQdcmLib;
+    bool  mBootAnimCompleted;
+};
+
 // -----------------------------------------------------------------------------
 // HWC context
 // This structure contains overall state
@@ -698,6 +709,8 @@
     bool mBootAnimCompleted;
     // Display binder service
     qService::QService* mQService;
+    //struct holds the information about display tuning service library.
+    struct qdcm_info mQdcmInfo;
 };
 
 namespace qhwc {
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 6a9d7f8..30578bc 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -63,6 +63,7 @@
         SET_FRAME_DUMP_CONFIG = 21,  // Provides ability to set the frame dump config
         SET_S3D_MODE = 22, // Set the 3D mode as specified in msm_hdmi_modes.h
         CONNECT_HDMI_CLIENT = 23,  // Connect HDMI CEC HAL Client
+        QDCM_SVC_CMDS = 24,        // request QDCM services.
         SET_ACTIVE_CONFIG = 25, //Set a specified display config
         GET_ACTIVE_CONFIG = 26, //Get the current config index
         GET_CONFIG_COUNT = 27, //Get the number of supported display configs