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 *)¶ms, (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 *)¶ms, (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 *)¶ms, (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 *)¶ms, (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 *)¶ms, 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 *)¶ms, (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 *)¶ms, 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 *)¶ms, (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 *)¶ms, (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