Merge "sde: resource: rotator yuv downscaling output alignment"
diff --git a/Android.mk b/Android.mk
index 5070911..6baef4a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,4 +1,4 @@
-ifeq ($(call is-board-platform-in-list, thulium),true)
+ifeq ($(call is-board-platform-in-list, msm8996),true)
TARGET_USES_SDE = true
else
TARGET_USES_SDE = false
diff --git a/displayengine/include/private/hw_info_types.h b/displayengine/include/private/hw_info_types.h
new file mode 100644
index 0000000..d842167
--- /dev/null
+++ b/displayengine/include/private/hw_info_types.h
@@ -0,0 +1,134 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+/*! @file hw_info_types.h
+ @brief Definitions for types that contain information pertaining to hardware devices.
+*/
+
+#ifndef __HW_INFO_TYPES_H__
+#define __HW_INFO_TYPES_H__
+
+#include <stdint.h>
+#include <core/sde_types.h>
+
+namespace sde {
+
+/*! @brief This enumeration holds the possible hardware device types. */
+enum HWDeviceType {
+ kDevicePrimary,
+ kDeviceHDMI,
+ kDeviceVirtual,
+ kDeviceRotator,
+ kDeviceMax,
+};
+
+/*! @brief This structure is a representation of hardware capabilities of the target device display
+ driver.
+*/
+struct HWResourceInfo {
+ uint32_t hw_version;
+ uint32_t hw_revision;
+ uint32_t num_dma_pipe;
+ uint32_t num_vig_pipe;
+ uint32_t num_rgb_pipe;
+ uint32_t num_cursor_pipe;
+ uint32_t num_blending_stages;
+ uint32_t num_rotator;
+ uint32_t num_control;
+ uint32_t num_mixer_to_disp;
+ uint32_t smp_total;
+ uint32_t smp_size;
+ uint32_t num_smp_per_pipe;
+ uint32_t max_scale_up;
+ uint32_t max_scale_down;
+ uint64_t max_bandwidth_low;
+ uint64_t max_bandwidth_high;
+ uint32_t max_mixer_width;
+ uint32_t max_pipe_bw;
+ uint32_t max_sde_clk;
+ float clk_fudge_factor;
+ bool has_bwc;
+ bool has_decimation;
+ bool has_macrotile;
+ bool has_rotator_downscale;
+ bool has_non_scalar_rgb;
+ bool is_src_split;
+
+ HWResourceInfo()
+ : hw_version(0), hw_revision(0), num_dma_pipe(0), num_vig_pipe(0), num_rgb_pipe(0),
+ num_cursor_pipe(0), num_blending_stages(0), num_rotator(0), num_control(0),
+ num_mixer_to_disp(0), smp_total(0), smp_size(0), num_smp_per_pipe(0), max_scale_up(1),
+ max_scale_down(1), max_bandwidth_low(0), max_bandwidth_high(0), max_mixer_width(2048),
+ max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false),
+ has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
+ has_non_scalar_rgb(false), is_src_split(false) { }
+
+ void Reset() { *this = HWResourceInfo(); }
+};
+
+/*! @brief This enumeration holds the all possible panel types. */
+enum HWPanelType {
+ kNoPanel,
+ kCommandModePanel,
+ kVideoModePanel,
+ kDTvPanel,
+ kWriteBackPanel,
+ kLVDSPanel,
+ kEDPPanel,
+};
+
+/*! @brief This structure describes the split configuration of a display panel. */
+struct HWSplitInfo {
+ uint32_t left_split;
+ uint32_t right_split;
+ bool always_src_split;
+ HWSplitInfo() : left_split(0), right_split(0), always_src_split(false) { }
+};
+
+/*! @brief This structure describes properties of a display panel. */
+struct HWPanelInfo {
+ HWPanelType type; //!< Panel type
+ bool partial_update; //!< Partial update feature
+ int left_align; //!< ROI left alignment restriction
+ int width_align; //!< ROI width alignment restriction
+ int top_align;; //!< ROI top alignment restriction
+ int height_align; //!< ROI height alignment restriction
+ int min_roi_width; //!< Min width needed for ROI
+ int min_roi_height; //!< Min height needed for ROI
+ bool needs_roi_merge; //!< Merge ROI's of both the DSI's
+ bool dynamic_fps; //!< Panel Supports dynamic fps
+ uint32_t min_fps; //!< Min fps supported by panel
+ uint32_t max_fps; //!< Max fps supported by panel
+ bool is_primary_panel; //!< Panel is primary display
+ HWSplitInfo split_info; //!< Panel split configuration
+
+ HWPanelInfo() : type(kNoPanel), partial_update(false), left_align(false), width_align(false),
+ top_align(false), height_align(false), min_roi_width(0), min_roi_height(0),
+ needs_roi_merge(false), dynamic_fps(false), min_fps(0), max_fps(0) { }
+};
+
+} // namespace sde
+
+#endif // __HW_INFO_TYPES_H__
+
diff --git a/displayengine/libs/core/Android.mk b/displayengine/libs/core/Android.mk
index b7d2478..5623283 100644
--- a/displayengine/libs/core/Android.mk
+++ b/displayengine/libs/core/Android.mk
@@ -12,6 +12,7 @@
LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/scalar/inc
LOCAL_CFLAGS += -DUSES_SCALAR
endif
+LOCAL_HW_INTF_PATH := fb
LOCAL_SHARED_LIBRARIES := libdl libsdeutils libcutils
LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
LOCAL_SRC_FILES := core_interface.cpp \
@@ -25,10 +26,14 @@
res_manager.cpp \
res_config.cpp \
offline_ctrl.cpp \
- hw_interface.cpp \
- hw_framebuffer.cpp \
dump_impl.cpp \
buffer_manager.cpp \
- scalar_helper.cpp
+ scalar_helper.cpp \
+ $(LOCAL_HW_INTF_PATH)/hw_info.cpp \
+ $(LOCAL_HW_INTF_PATH)/hw_device.cpp \
+ $(LOCAL_HW_INTF_PATH)/hw_primary.cpp \
+ $(LOCAL_HW_INTF_PATH)/hw_rotator.cpp \
+ $(LOCAL_HW_INTF_PATH)/hw_hdmi.cpp \
+ $(LOCAL_HW_INTF_PATH)/hw_virtual.cpp
include $(BUILD_SHARED_LIBRARY)
diff --git a/displayengine/libs/core/core_impl.cpp b/displayengine/libs/core/core_impl.cpp
index bd6ab9a..2732889 100644
--- a/displayengine/libs/core/core_impl.cpp
+++ b/displayengine/libs/core/core_impl.cpp
@@ -30,6 +30,7 @@
#include "display_primary.h"
#include "display_hdmi.h"
#include "display_virtual.h"
+#include "hw_info_interface.h"
#define __CLASS__ "CoreImpl"
@@ -38,40 +39,50 @@
CoreImpl::CoreImpl(CoreEventHandler *event_handler, BufferAllocator *buffer_allocator,
BufferSyncHandler *buffer_sync_handler)
: event_handler_(event_handler), buffer_allocator_(buffer_allocator),
- buffer_sync_handler_(buffer_sync_handler), hw_intf_(NULL) {
+ buffer_sync_handler_(buffer_sync_handler), hw_resource_(NULL) {
}
DisplayError CoreImpl::Init() {
SCOPE_LOCK(locker_);
-
DisplayError error = kErrorNone;
- error = HWInterface::Create(&hw_intf_, buffer_sync_handler_);
- if (UNLIKELY(error != kErrorNone)) {
+ error = HWInfoInterface::Create(&hw_info_intf_);
+ if (error != kErrorNone) {
return error;
}
- HWResourceInfo hw_res_info;
- error = hw_intf_->GetHWCapabilities(&hw_res_info);
- if (UNLIKELY(error != kErrorNone)) {
- HWInterface::Destroy(hw_intf_);
- return error;
+ hw_resource_ = new HWResourceInfo();
+ if (!hw_resource_) {
+ error = kErrorMemory;
+ goto CleanUpOnError;
}
- error = comp_mgr_.Init(hw_res_info, buffer_allocator_, buffer_sync_handler_);
- if (UNLIKELY(error != kErrorNone)) {
- HWInterface::Destroy(hw_intf_);
- return error;
+ error = hw_info_intf_->GetHWResourceInfo(hw_resource_);
+ if (error != kErrorNone) {
+ goto CleanUpOnError;
}
- error = offline_ctrl_.Init(hw_intf_, hw_res_info);
- if (UNLIKELY(error != kErrorNone)) {
+ error = comp_mgr_.Init(*hw_resource_, buffer_allocator_, buffer_sync_handler_);
+ if (error != kErrorNone) {
comp_mgr_.Deinit();
- HWInterface::Destroy(hw_intf_);
- return error;
+ goto CleanUpOnError;
}
+ error = offline_ctrl_.Init(buffer_sync_handler_);
+ if (error != kErrorNone) {
+ goto CleanUpOnError;
+ }
return kErrorNone;
+
+CleanUpOnError:
+ if (hw_resource_) {
+ delete hw_resource_;
+ hw_resource_ = NULL;
+ }
+
+ HWInfoInterface::Destroy(hw_info_intf_);
+
+ return error;
}
DisplayError CoreImpl::Deinit() {
@@ -79,7 +90,7 @@
offline_ctrl_.Deinit();
comp_mgr_.Deinit();
- HWInterface::Destroy(hw_intf_);
+ HWInfoInterface::Destroy(hw_info_intf_);
return kErrorNone;
}
@@ -88,24 +99,25 @@
DisplayInterface **intf) {
SCOPE_LOCK(locker_);
- if (UNLIKELY(!event_handler || !intf)) {
+ if (!event_handler || !intf) {
return kErrorParameters;
}
DisplayBase *display_base = NULL;
+
switch (type) {
case kPrimary:
- display_base = new DisplayPrimary(event_handler, hw_intf_, &comp_mgr_, &offline_ctrl_);
+ display_base = new DisplayPrimary(event_handler, hw_info_intf_, buffer_sync_handler_,
+ &comp_mgr_, &offline_ctrl_);
break;
-
case kHDMI:
- display_base = new DisplayHDMI(event_handler, hw_intf_, &comp_mgr_, &offline_ctrl_);
+ display_base = new DisplayHDMI(event_handler, hw_info_intf_, buffer_sync_handler_,
+ &comp_mgr_, &offline_ctrl_);
break;
-
case kVirtual:
- display_base = new DisplayVirtual(event_handler, hw_intf_, &comp_mgr_, &offline_ctrl_);
+ display_base = new DisplayVirtual(event_handler, hw_info_intf_, buffer_sync_handler_,
+ &comp_mgr_, &offline_ctrl_);
break;
-
default:
DLOGE("Spurious display type %d", type);
return kErrorParameters;
@@ -116,7 +128,8 @@
}
DisplayError error = display_base->Init();
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
+ display_base->Deinit();
delete display_base;
display_base = NULL;
return error;
@@ -129,7 +142,7 @@
DisplayError CoreImpl::DestroyDisplay(DisplayInterface *intf) {
SCOPE_LOCK(locker_);
- if (UNLIKELY(!intf)) {
+ if (!intf) {
return kErrorParameters;
}
diff --git a/displayengine/libs/core/core_impl.h b/displayengine/libs/core/core_impl.h
index e289a23..03733a8 100644
--- a/displayengine/libs/core/core_impl.h
+++ b/displayengine/libs/core/core_impl.h
@@ -37,6 +37,8 @@
namespace sde {
+class HWInfoInterface;
+
class CoreImpl : public CoreInterface {
public:
// This class implements display core interface revision 1.0.
@@ -62,9 +64,10 @@
CoreEventHandler *event_handler_;
BufferAllocator *buffer_allocator_;
BufferSyncHandler *buffer_sync_handler_;
- HWInterface *hw_intf_;
+ HWResourceInfo *hw_resource_;
CompManager comp_mgr_;
OfflineCtrl offline_ctrl_;
+ HWInfoInterface *hw_info_intf_;
};
} // namespace sde
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 8bfc6dd..b61d3a6 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -34,28 +34,30 @@
// TODO(user): Have a single structure handle carries all the interface pointers and variables.
DisplayBase::DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
- HWDeviceType hw_device_type, HWInterface *hw_intf,
+ HWDeviceType hw_device_type, BufferSyncHandler *buffer_sync_handler,
CompManager *comp_manager, OfflineCtrl *offline_ctrl)
: display_type_(display_type), event_handler_(event_handler), hw_device_type_(hw_device_type),
- hw_intf_(hw_intf), comp_manager_(comp_manager), offline_ctrl_(offline_ctrl), state_(kStateOff),
- hw_device_(0), display_comp_ctx_(0), display_attributes_(NULL), num_modes_(0),
- active_mode_index_(0), pending_commit_(false), vsync_enable_(false) {
+ buffer_sync_handler_(buffer_sync_handler), comp_manager_(comp_manager),
+ offline_ctrl_(offline_ctrl), state_(kStateOff), hw_device_(0), display_comp_ctx_(0),
+ display_attributes_(NULL), num_modes_(0), active_mode_index_(0), pending_commit_(false),
+ vsync_enable_(false) {
}
DisplayError DisplayBase::Init() {
- SCOPE_LOCK(locker_);
-
DisplayError error = kErrorNone;
- error = hw_intf_->Open(hw_device_type_, &hw_device_, this);
+ error = hw_intf_->Open(this);
if (error != kErrorNone) {
return error;
}
- // Set the idle timeout value to driver through sysfs node
- hw_intf_->SetIdleTimeoutMs(hw_device_, Debug::GetIdleTimeoutMs());
+ panel_info_ = HWPanelInfo();
+ hw_intf_->GetHWPanelInfo(&panel_info_);
- error = hw_intf_->GetNumDisplayAttributes(hw_device_, &num_modes_);
+ // Set the idle timeout value to driver through sysfs node
+ SetIdleTimeoutMs(Debug::GetIdleTimeoutMs());
+
+ error = hw_intf_->GetNumDisplayAttributes(&num_modes_);
if (error != kErrorNone) {
goto CleanupOnError;
}
@@ -67,7 +69,7 @@
}
for (uint32_t i = 0; i < num_modes_; i++) {
- error = hw_intf_->GetDisplayAttributes(hw_device_, &display_attributes_[i], i);
+ error = hw_intf_->GetDisplayAttributes(&display_attributes_[i], i);
if (error != kErrorNone) {
goto CleanupOnError;
}
@@ -75,7 +77,7 @@
active_mode_index_ = GetBestConfig();
- error = hw_intf_->SetDisplayAttributes(hw_device_, active_mode_index_);
+ error = hw_intf_->SetDisplayAttributes(active_mode_index_);
if (error != kErrorNone) {
goto CleanupOnError;
}
@@ -103,14 +105,12 @@
display_attributes_ = NULL;
}
- hw_intf_->Close(hw_device_);
+ hw_intf_->Close();
return error;
}
DisplayError DisplayBase::Deinit() {
- SCOPE_LOCK(locker_);
-
offline_ctrl_->UnregisterDisplay(display_offline_ctx_);
comp_manager_->UnregisterDisplay(display_comp_ctx_);
@@ -120,7 +120,7 @@
display_attributes_ = NULL;
}
- hw_intf_->Close(hw_device_);
+ hw_intf_->Close();
return kErrorNone;
}
@@ -150,7 +150,7 @@
error = offline_ctrl_->Prepare(display_offline_ctx_, &hw_layers_);
if (error == kErrorNone) {
- error = hw_intf_->Validate(hw_device_, &hw_layers_);
+ error = hw_intf_->Validate(&hw_layers_);
if (error == kErrorNone) {
// Strategy is successful now, wait for Commit().
pending_commit_ = true;
@@ -183,7 +183,7 @@
error = offline_ctrl_->Commit(display_offline_ctx_, &hw_layers_);
if (error == kErrorNone) {
- error = hw_intf_->Commit(hw_device_, &hw_layers_);
+ error = hw_intf_->Commit(&hw_layers_);
if (error == kErrorNone) {
error = comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
if (error != kErrorNone) {
@@ -212,7 +212,7 @@
}
hw_layers_.info.count = 0;
- error = hw_intf_->Flush(hw_device_);
+ error = hw_intf_->Flush();
if (error == kErrorNone) {
comp_manager_->Purge(display_comp_ctx_);
pending_commit_ = false;
@@ -305,24 +305,24 @@
switch (state) {
case kStateOff:
hw_layers_.info.count = 0;
- error = hw_intf_->Flush(hw_device_);
+ error = hw_intf_->Flush();
if (error == kErrorNone) {
comp_manager_->Purge(display_comp_ctx_);
- error = hw_intf_->PowerOff(hw_device_);
+ error = hw_intf_->PowerOff();
}
break;
case kStateOn:
- error = hw_intf_->PowerOn(hw_device_);
+ error = hw_intf_->PowerOn();
break;
case kStateDoze:
- error = hw_intf_->Doze(hw_device_);
+ error = hw_intf_->Doze();
break;
case kStateStandby:
- error = hw_intf_->Standby(hw_device_);
+ error = hw_intf_->Standby();
break;
default:
@@ -375,7 +375,7 @@
return kErrorParameters;
}
- error = hw_intf_->SetDisplayAttributes(hw_device_, index);
+ error = hw_intf_->SetDisplayAttributes(index);
if (error != kErrorNone) {
return error;
}
@@ -393,21 +393,10 @@
}
DisplayError DisplayBase::SetVSyncState(bool enable) {
- SCOPE_LOCK(locker_);
- DisplayError error = kErrorNone;
- if (vsync_enable_ != enable) {
- error = hw_intf_->SetVSyncState(hw_device_, enable);
- if (error == kErrorNone) {
- vsync_enable_ = enable;
- }
- }
-
- return error;
+ return kErrorNotSupported;
}
-void DisplayBase::SetIdleTimeoutMs(uint32_t timeout_ms) {
- hw_intf_->SetIdleTimeoutMs(hw_device_, timeout_ms);
-}
+void DisplayBase::SetIdleTimeoutMs(uint32_t timeout_ms) { }
DisplayError DisplayBase::SetMaxMixerStages(uint32_t max_mixer_stages) {
SCOPE_LOCK(locker_);
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 10e11f8..51b0ac3 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -41,8 +41,8 @@
class DisplayBase : public DisplayInterface, HWEventHandler, DumpImpl {
public:
DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
- HWDeviceType hw_device_type, HWInterface *hw_intf, CompManager *comp_manager,
- OfflineCtrl *offline_ctrl);
+ HWDeviceType hw_device_type, BufferSyncHandler *buffer_sync_handler,
+ CompManager *comp_manager, OfflineCtrl *offline_ctrl);
virtual ~DisplayBase() { }
virtual DisplayError Init();
virtual DisplayError Deinit();
@@ -79,6 +79,8 @@
DisplayEventHandler *event_handler_;
HWDeviceType hw_device_type_;
HWInterface *hw_intf_;
+ HWPanelInfo panel_info_;
+ BufferSyncHandler *buffer_sync_handler_;
CompManager *comp_manager_;
OfflineCtrl *offline_ctrl_;
DisplayState state_;
diff --git a/displayengine/libs/core/display_hdmi.cpp b/displayengine/libs/core/display_hdmi.cpp
index ed2a859..045c06c 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -26,14 +26,49 @@
#include <utils/debug.h>
#include "display_hdmi.h"
+#include "hw_hdmi_interface.h"
+#include "hw_info_interface.h"
#define __CLASS__ "DisplayHDMI"
namespace sde {
-DisplayHDMI::DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf,
- CompManager *comp_manager, OfflineCtrl *offline_ctrl)
- : DisplayBase(kHDMI, event_handler, kDeviceHDMI, hw_intf, comp_manager, offline_ctrl) { }
+DisplayHDMI::DisplayHDMI(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
+ OfflineCtrl *offline_ctrl)
+ : DisplayBase(kHDMI, event_handler, kDeviceHDMI, buffer_sync_handler, comp_manager,
+ offline_ctrl), hw_info_intf_(hw_info_intf) {
+}
+
+DisplayError DisplayHDMI::Init() {
+ SCOPE_LOCK(locker_);
+
+ DisplayError error = HWHDMIInterface::Create(&hw_hdmi_intf_, hw_info_intf_,
+ DisplayBase::buffer_sync_handler_);
+ if (error != kErrorNone) {
+ return error;
+ }
+ DisplayBase::hw_intf_ = hw_hdmi_intf_;
+
+ error = DisplayBase::Init();
+ if (error != kErrorNone) {
+ HWHDMIInterface::Destroy(hw_hdmi_intf_);
+ }
+
+ return error;
+}
+
+DisplayError DisplayHDMI::Deinit() {
+ SCOPE_LOCK(locker_);
+
+ DisplayError error = DisplayBase::Deinit();
+ if (error != kErrorNone) {
+ return error;
+ }
+ HWHDMIInterface::Destroy(hw_hdmi_intf_);
+
+ return error;
+}
int DisplayHDMI::GetBestConfig() {
uint32_t best_config_mode = 0;
@@ -68,7 +103,7 @@
if (user_config) {
uint32_t config_index = -1;
// For the config, get the corresponding index
- DisplayError error = hw_intf_->GetConfigIndex(hw_device_, user_config, &config_index);
+ DisplayError error = hw_intf_->GetConfigIndex(user_config, &config_index);
if (error == kErrorNone)
return config_index;
}
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 91e4797..506329b 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -29,11 +29,21 @@
namespace sde {
+class HWHDMIInterface;
+class HWInfoInterface;
+
class DisplayHDMI : public DisplayBase {
public:
- DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager,
+ DisplayHDMI(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
OfflineCtrl *offline_ctrl);
+ virtual DisplayError Init();
+ virtual DisplayError Deinit();
virtual int GetBestConfig();
+
+ private:
+ HWHDMIInterface *hw_hdmi_intf_;
+ HWInfoInterface *hw_info_intf_;
};
} // namespace sde
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
index 8eed8ee..55e927c 100644
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -26,14 +26,71 @@
#include <utils/debug.h>
#include "display_primary.h"
+#include "hw_primary_interface.h"
+#include "hw_info_interface.h"
#define __CLASS__ "DisplayPrimary"
namespace sde {
-DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInterface *hw_intf,
- CompManager *comp_manager, OfflineCtrl *offline_ctrl)
- : DisplayBase(kPrimary, event_handler, kDevicePrimary, hw_intf, comp_manager, offline_ctrl) { }
+DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
+ OfflineCtrl *offline_ctrl)
+ : DisplayBase(kPrimary, event_handler, kDevicePrimary, buffer_sync_handler, comp_manager,
+ offline_ctrl), hw_info_intf_(hw_info_intf) {
+}
+
+DisplayError DisplayPrimary::Init() {
+ SCOPE_LOCK(locker_);
+
+ DisplayError error = HWPrimaryInterface::Create(&hw_primary_intf_, hw_info_intf_,
+ DisplayBase::buffer_sync_handler_);
+ if (error != kErrorNone) {
+ return error;
+ }
+ DisplayBase::hw_intf_ = hw_primary_intf_;
+
+ error = DisplayBase::Init();
+ if (error != kErrorNone) {
+ HWPrimaryInterface::Destroy(hw_primary_intf_);
+ }
+
+ return error;
+}
+
+DisplayError DisplayPrimary::Deinit() {
+ SCOPE_LOCK(locker_);
+
+ DisplayError error = DisplayBase::Deinit();
+ if (error != kErrorNone) {
+ return error;
+ }
+ HWPrimaryInterface::Destroy(hw_primary_intf_);
+
+ return error;
+}
+
+DisplayError DisplayPrimary::SetVSyncState(bool enable) {
+ SCOPE_LOCK(locker_);
+ DisplayError error = kErrorNone;
+ if (vsync_enable_ != enable) {
+ error = hw_primary_intf_->SetVSyncState(enable);
+ if (error == kErrorNone) {
+ vsync_enable_ = enable;
+ }
+ }
+
+ return error;
+}
+
+void DisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+ // Idle fallback feature is supported only for video mode panel.
+ if (panel_info_.type == kCommandModePanel) {
+ return;
+ }
+
+ hw_primary_intf_->SetIdleTimeoutMs(timeout_ms);
+}
} // namespace sde
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index ea4cf2b..76fbb06 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -29,10 +29,22 @@
namespace sde {
+class HWPrimaryInterface;
+class HWInfoInterface;
+
class DisplayPrimary : public DisplayBase {
public:
- DisplayPrimary(DisplayEventHandler *event_handler, HWInterface *hw_intf,
- CompManager *comp_manager, OfflineCtrl *offline_ctrl);
+ DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
+ OfflineCtrl *offline_ctrl);
+ virtual DisplayError Init();
+ virtual DisplayError Deinit();
+ virtual DisplayError SetVSyncState(bool enable);
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+
+ private:
+ HWPrimaryInterface *hw_primary_intf_;
+ HWInfoInterface *hw_info_intf_;
};
} // namespace sde
diff --git a/displayengine/libs/core/display_virtual.cpp b/displayengine/libs/core/display_virtual.cpp
index 84a825f..359e6a3 100644
--- a/displayengine/libs/core/display_virtual.cpp
+++ b/displayengine/libs/core/display_virtual.cpp
@@ -26,14 +26,49 @@
#include <utils/debug.h>
#include "display_virtual.h"
+#include "hw_virtual_interface.h"
+#include "hw_info_interface.h"
#define __CLASS__ "DisplayVirtual"
namespace sde {
-DisplayVirtual::DisplayVirtual(DisplayEventHandler *event_handler, HWInterface *hw_intf,
- CompManager *comp_manager, OfflineCtrl *offline_ctrl)
- : DisplayBase(kVirtual, event_handler, kDeviceVirtual, hw_intf, comp_manager, offline_ctrl) { }
+DisplayVirtual::DisplayVirtual(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
+ OfflineCtrl *offline_ctrl)
+ : DisplayBase(kVirtual, event_handler, kDeviceVirtual, buffer_sync_handler, comp_manager,
+ offline_ctrl), hw_info_intf_(hw_info_intf) {
+}
+
+DisplayError DisplayVirtual::Init() {
+ SCOPE_LOCK(locker_);
+
+ DisplayError error = HWVirtualInterface::Create(&hw_virtual_intf_, hw_info_intf_,
+ DisplayBase::buffer_sync_handler_);
+ if (error != kErrorNone) {
+ return error;
+ }
+ DisplayBase::hw_intf_ = hw_virtual_intf_;
+
+ error = DisplayBase::Init();
+ if (error != kErrorNone) {
+ HWVirtualInterface::Destroy(hw_virtual_intf_);
+ }
+
+ return error;
+}
+
+DisplayError DisplayVirtual::Deinit() {
+ SCOPE_LOCK(locker_);
+
+ DisplayError error = DisplayBase::Deinit();
+ if (error != kErrorNone) {
+ return error;
+ }
+ HWVirtualInterface::Destroy(hw_virtual_intf_);
+
+ return error;
+}
} // namespace sde
diff --git a/displayengine/libs/core/display_virtual.h b/displayengine/libs/core/display_virtual.h
index 9697702..7dee9fa 100644
--- a/displayengine/libs/core/display_virtual.h
+++ b/displayengine/libs/core/display_virtual.h
@@ -29,10 +29,20 @@
namespace sde {
+class HWVirtualInterface;
+class HWInfoInterface;
+
class DisplayVirtual : public DisplayBase {
public:
- DisplayVirtual(DisplayEventHandler *event_handler, HWInterface *hw_intf,
- CompManager *comp_manager, OfflineCtrl *offline_ctrl);
+ DisplayVirtual(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
+ OfflineCtrl *offline_ctrl);
+ virtual DisplayError Init();
+ virtual DisplayError Deinit();
+
+ private:
+ HWVirtualInterface *hw_virtual_intf_;
+ HWInfoInterface *hw_info_intf_;
};
} // namespace sde
diff --git a/displayengine/libs/core/fb/hw_device.cpp b/displayengine/libs/core/fb/hw_device.cpp
new file mode 100644
index 0000000..ed19d80
--- /dev/null
+++ b/displayengine/libs/core/fb/hw_device.cpp
@@ -0,0 +1,817 @@
+/*
+* Copyright (c) 2014 - 2015, 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.
+*/
+
+#define __STDC_FORMAT_MACROS
+#include <ctype.h>
+#include <math.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+
+#include "hw_device.h"
+#include "scalar_helper.h"
+
+#define __CLASS__ "HWDevice"
+
+#ifdef DISPLAY_CORE_VIRTUAL_DRIVER
+extern int virtual_ioctl(int fd, int cmd, ...);
+extern int virtual_open(const char *file_name, int access, ...);
+extern int virtual_close(int fd);
+extern int virtual_poll(struct pollfd *fds, nfds_t num, int timeout);
+extern ssize_t virtual_pread(int fd, void *data, size_t count, off_t offset);
+extern ssize_t virtual_pwrite(int fd, const void *data, size_t count, off_t offset);
+extern FILE* virtual_fopen(const char *fname, const char *mode);
+extern int virtual_fclose(FILE* fileptr);
+extern ssize_t virtual_getline(char **lineptr, size_t *linelen, FILE *stream);
+
+#endif
+
+namespace sde {
+
+HWDevice::HWDevice(BufferSyncHandler *buffer_sync_handler)
+ : fb_node_index_(-1), fb_path_("/sys/devices/virtual/graphics/fb"), hotplug_enabled_(false),
+ buffer_sync_handler_(buffer_sync_handler) {
+ // Pointer to actual driver interfaces.
+ ioctl_ = ::ioctl;
+ open_ = ::open;
+ close_ = ::close;
+ poll_ = ::poll;
+ pread_ = ::pread;
+ pwrite_ = ::pwrite;
+ fopen_ = ::fopen;
+ fclose_ = ::fclose;
+ getline_ = ::getline;
+
+#ifdef DISPLAY_CORE_VIRTUAL_DRIVER
+ // If debug property to use virtual driver is set, point to virtual driver interfaces.
+ if (Debug::IsVirtualDriver()) {
+ ioctl_ = virtual_ioctl;
+ open_ = virtual_open;
+ close_ = virtual_close;
+ poll_ = virtual_poll;
+ pread_ = virtual_pread;
+ pwrite_ = virtual_pwrite;
+ fopen_ = virtual_fopen;
+ fclose_ = virtual_fclose;
+ getline_ = virtual_getline;
+ }
+#endif
+}
+
+DisplayError HWDevice::Init() {
+ DisplayError error = kErrorNone;
+
+ // Read the fb node index
+ fb_node_index_ = GetFBNodeIndex(device_type_);
+ if (fb_node_index_ == -1) {
+ DLOGE("%s should be present", device_name_);
+ return kErrorHardware;
+ }
+
+ // Populate Panel Info (Used for Partial Update)
+ PopulateHWPanelInfo();
+ // Populate HW Capabilities
+ hw_resource_ = HWResourceInfo();
+ hw_info_intf_->GetHWResourceInfo(&hw_resource_);
+
+ return error;
+}
+
+DisplayError HWDevice::Open(HWEventHandler *eventhandler) {
+ DisplayError error = kErrorNone;
+
+ char device_name[64] = {0};
+
+ // Store EventHandlers for two Physical displays, i.e., Primary and HDMI
+ // TODO(user): Need to revisit for HDMI as Primary usecase
+ event_handler_ = eventhandler;
+ snprintf(device_name, sizeof(device_name), "%s%d", "/dev/graphics/fb", fb_node_index_);
+
+ device_fd_ = open_(device_name, O_RDWR);
+ if (device_fd_ < 0) {
+ DLOGE("open %s failed err = %d errstr = %s", device_name, errno, strerror(errno));
+ return kErrorResources;
+ }
+
+ return error;
+}
+
+DisplayError HWDevice::Close() {
+ if (device_fd_ > 0) {
+ close_(device_fd_);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWDevice::GetNumDisplayAttributes(uint32_t *count) {
+ *count = 1;
+ return kErrorNone;
+}
+
+DisplayError HWDevice::GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+ uint32_t index) {
+ return kErrorNone;
+}
+
+DisplayError HWDevice::GetHWPanelInfo(HWPanelInfo *panel_info) {
+ *panel_info = panel_info_;
+ return kErrorNone;
+}
+
+DisplayError HWDevice::SetDisplayAttributes(uint32_t index) {
+ return kErrorNone;
+}
+
+DisplayError HWDevice::GetConfigIndex(uint32_t mode, uint32_t *index) {
+ return kErrorNone;
+}
+
+
+DisplayError HWDevice::PowerOn() {
+ DTRACE_SCOPED();
+
+ if (ioctl_(device_fd_, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
+ IOCTL_LOGE(FB_BLANK_UNBLANK, device_type_);
+ return kErrorHardware;
+ }
+
+ // Need to turn on HPD
+ if (!hotplug_enabled_) {
+ hotplug_enabled_ = EnableHotPlugDetection(1);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWDevice::PowerOff() {
+ return kErrorNone;
+}
+
+DisplayError HWDevice::Doze() {
+ return kErrorNone;
+}
+
+DisplayError HWDevice::Standby() {
+ return kErrorNone;
+}
+
+DisplayError HWDevice::Validate(HWLayers *hw_layers) {
+ DTRACE_SCOPED();
+
+ DisplayError error = kErrorNone;
+ ResetDisplayParams();
+
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ LayerStack *stack = hw_layer_info.stack;
+
+ DLOGV_IF(kTagDriverConfig, "************************** %s Validate Input ***********************",
+ device_name_);
+ DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
+
+ mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+ uint32_t &mdp_layer_count = mdp_commit.input_layer_cnt;
+
+ for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+ uint32_t layer_index = hw_layer_info.index[i];
+ Layer &layer = stack->layers[layer_index];
+ LayerBuffer *input_buffer = layer.input_buffer;
+ HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+ HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
+ mdp_input_layer mdp_layer;
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
+ HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+ if (rotate_info->valid) {
+ input_buffer = &rotate_info->hw_buffer_info.output_buffer;
+ }
+
+ if (pipe_info->valid) {
+ mdp_input_layer &mdp_layer = mdp_in_layers_[mdp_layer_count];
+ mdp_layer_buffer &mdp_buffer = mdp_layer.buffer;
+
+ mdp_buffer.width = input_buffer->width;
+ mdp_buffer.height = input_buffer->height;
+
+ error = SetFormat(input_buffer->format, &mdp_buffer.format);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ mdp_layer.alpha = layer.plane_alpha;
+ mdp_layer.z_order = UINT16(pipe_info->z_order);
+ mdp_layer.transp_mask = 0xffffffff;
+ SetBlending(layer.blending, &mdp_layer.blend_op);
+ mdp_layer.pipe_ndx = pipe_info->pipe_id;
+ mdp_layer.horz_deci = pipe_info->horizontal_decimation;
+ mdp_layer.vert_deci = pipe_info->vertical_decimation;
+
+ SetRect(pipe_info->src_roi, &mdp_layer.src_rect);
+ SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect);
+
+ // Flips will be taken care by rotator, if layer requires 90 rotation. So Dont use MDP for
+ // flip operation, if layer transform is 90.
+ if (!layer.transform.rotation) {
+ 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_scale_data* mdp_scale = GetScaleDataRef(mdp_layer_count);
+#ifdef USES_SCALAR
+ // Set the configured scale data for MDP driver
+ ScalarHelper::GetInstance()->SetScaleData(i, !count, mdp_scale);
+ if (mdp_scale->enable_pxl_ext) {
+ if ((mdp_layer.flags & MDP_LAYER_DEINTERLACE) && (layer.transform.rotation == 90.0f))
+ ScalarHelper::GetInstance()->UpdateSrcWidth(i, !count, &mdp_buffer.width);
+ }
+#endif
+ mdp_layer.scale = mdp_scale;
+
+ mdp_layer_count++;
+
+ DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
+ i, count ? "Right" : "Left");
+ DLOGV_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d", mdp_buffer.width, mdp_buffer.height,
+ mdp_buffer.format);
+ DLOGV_IF(kTagDriverConfig, "plane_alpha %d, zorder %d, blending %d, horz_deci %d, "
+ "vert_deci %d", mdp_layer.alpha, mdp_layer.z_order, mdp_layer.blend_op,
+ mdp_layer.horz_deci, mdp_layer.vert_deci);
+ DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_layer.src_rect.x,
+ mdp_layer.src_rect.y, mdp_layer.src_rect.w, mdp_layer.src_rect.h);
+ DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_layer.dst_rect.x,
+ mdp_layer.dst_rect.y, mdp_layer.dst_rect.w, mdp_layer.dst_rect.h);
+ for (int j = 0; j < MAX_PLANES; j++) {
+ DLOGV_IF(kTagDriverConfig, "Scale Data[%d]: Phase=[%x %x %x %x] Pixel_Ext=[%d %d %d %d]",
+ j, mdp_layer.scale->init_phase_x[j], mdp_layer.scale->phase_step_x[j],
+ mdp_layer.scale->init_phase_y[j], mdp_layer.scale->phase_step_y[j],
+ mdp_layer.scale->num_ext_pxls_left[j], mdp_layer.scale->num_ext_pxls_top[j],
+ mdp_layer.scale->num_ext_pxls_right[j], mdp_layer.scale->num_ext_pxls_btm[j]);
+ DLOGV_IF(kTagDriverConfig, "Fetch=[%d %d %d %d] Repeat=[%d %d %d %d] roi_width = %d",
+ mdp_layer.scale->left_ftch[j], mdp_layer.scale->top_ftch[j],
+ mdp_layer.scale->right_ftch[j], mdp_layer.scale->btm_ftch[j],
+ mdp_layer.scale->left_rpt[j], mdp_layer.scale->top_rpt[j],
+ mdp_layer.scale->right_rpt[j], mdp_layer.scale->btm_rpt[j],
+ mdp_layer.scale->roi_w[j]);
+ }
+ DLOGV_IF(kTagDriverConfig, "*************************************************************");
+ }
+ }
+ }
+
+ if (device_type_ == kDeviceVirtual) {
+ LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+ // TODO(user): Need to assign the writeback id from the resource manager, since the support
+ // has not been added hard coding it to 2 for now.
+ mdp_out_layer_.writeback_ndx = 2;
+ mdp_out_layer_.buffer.width = output_buffer->width;
+ mdp_out_layer_.buffer.height = output_buffer->height;
+ SetFormat(output_buffer->format, &mdp_out_layer_.buffer.format);
+
+ DLOGI_IF(kTagDriverConfig, "******************* Output buffer Info **********************");
+ DLOGI_IF(kTagDriverConfig, "out_w %d, out_h %d, out_f %d, wb_id %d",
+ mdp_out_layer_.buffer.width, mdp_out_layer_.buffer.height,
+ mdp_out_layer_.buffer.format, mdp_out_layer_.writeback_ndx);
+ DLOGI_IF(kTagDriverConfig, "*************************************************************");
+ }
+
+ mdp_commit.flags |= MDP_VALIDATE_LAYER;
+ if (ioctl_(device_fd_, MSMFB_ATOMIC_COMMIT, &mdp_disp_commit_) < 0) {
+ IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
+ DumpLayerCommit(mdp_disp_commit_);
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+void HWDevice::DumpLayerCommit(mdp_layer_commit &layer_commit) {
+ mdp_layer_commit_v1 &mdp_commit = layer_commit.commit_v1;
+ mdp_input_layer *mdp_layers = mdp_commit.input_layers;
+
+ DLOGE("mdp_commt: flags = %x, release fence = %x", mdp_commit.flags, mdp_commit.release_fence);
+ DLOGE("left_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.left_roi.x, mdp_commit.left_roi.y,
+ mdp_commit.left_roi.w, mdp_commit.left_roi.h);
+ DLOGE("right_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.right_roi.x,
+ mdp_commit.right_roi.y, mdp_commit.right_roi.w, mdp_commit.right_roi.h);
+ for (uint32_t i = 0; i < mdp_commit.input_layer_cnt; i++) {
+ DLOGE("mdp_commt: layer_cnt = %d, pipe_ndx = %x, zorder = %d, flags = %x",
+ i, mdp_layers[i].pipe_ndx, mdp_layers[i].z_order, mdp_layers[i].flags);
+ mdp_rect &src_rect = mdp_layers[i].src_rect;
+ DLOGE("src rect: x = %d, y = %d, w = %d, h = %d",
+ src_rect.x, src_rect.y, src_rect.w, src_rect.h);
+ mdp_rect &dst_rect = mdp_layers[i].dst_rect;
+ DLOGE("dst rect: x = %d, y = %d, w = %d, h = %d",
+ dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h);
+ }
+}
+
+DisplayError HWDevice::Commit(HWLayers *hw_layers) {
+ DTRACE_SCOPED();
+
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ LayerStack *stack = hw_layer_info.stack;
+
+ DLOGV_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
+ device_name_);
+ DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
+
+ mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+ uint32_t mdp_layer_index = 0;
+
+ for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+ uint32_t layer_index = hw_layer_info.index[i];
+ LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
+ HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+ HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
+ HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+ if (rotate_info->valid) {
+ input_buffer = &rotate_info->hw_buffer_info.output_buffer;
+ }
+
+ if (pipe_info->valid) {
+ mdp_layer_buffer &mdp_buffer = mdp_in_layers_[mdp_layer_index].buffer;
+ mdp_input_layer &mdp_layer = mdp_in_layers_[mdp_layer_index];
+ if (input_buffer->planes[0].fd >= 0) {
+ mdp_buffer.plane_count = 1;
+ mdp_buffer.planes[0].fd = input_buffer->planes[0].fd;
+ mdp_buffer.planes[0].offset = input_buffer->planes[0].offset;
+ SetStride(device_type_, input_buffer->format, input_buffer->planes[0].stride,
+ &mdp_buffer.planes[0].stride);
+ } else {
+ DLOGW("Invalid buffer fd, setting plane count to 0");
+ mdp_buffer.plane_count = 0;
+ }
+
+ mdp_buffer.fence = input_buffer->acquire_fence_fd;
+ mdp_layer_index++;
+
+ DLOGV_IF(kTagDriverConfig, "****************** Layer[%d] %s pipe Input *******************",
+ i, count ? "Right" : "Left");
+ DLOGI_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d, horz_deci %d, vert_deci %d",
+ mdp_buffer.width, mdp_buffer.height, mdp_buffer.format, mdp_layer.horz_deci,
+ mdp_layer.vert_deci);
+ DLOGI_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_buf_stride %d, " \
+ "in_plane_count %d, in_fence %d, layer count %d", mdp_buffer.planes[0].fd,
+ mdp_buffer.planes[0].offset, mdp_buffer.planes[0].stride, mdp_buffer.plane_count,
+ mdp_buffer.fence, mdp_commit.input_layer_cnt);
+ DLOGV_IF(kTagDriverConfig, "*************************************************************");
+ }
+ }
+ }
+ if (device_type_ == kDeviceVirtual) {
+ LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+
+ if (output_buffer->planes[0].fd >= 0) {
+ mdp_out_layer_.buffer.planes[0].fd = output_buffer->planes[0].fd;
+ mdp_out_layer_.buffer.planes[0].offset = output_buffer->planes[0].offset;
+ SetStride(device_type_, output_buffer->format, output_buffer->planes[0].stride,
+ &mdp_out_layer_.buffer.planes[0].stride);
+ mdp_out_layer_.buffer.plane_count = 1;
+ } else {
+ DLOGW("Invalid output buffer fd, setting plane count to 0");
+ mdp_out_layer_.buffer.plane_count = 0;
+ }
+
+ mdp_out_layer_.buffer.fence = output_buffer->acquire_fence_fd;
+
+ DLOGI_IF(kTagDriverConfig, "******************* Output buffer Info **********************");
+ DLOGI_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, acquire_fence %d",
+ mdp_out_layer_.buffer.planes[0].fd, mdp_out_layer_.buffer.planes[0].offset,
+ mdp_out_layer_.buffer.planes[0].stride, mdp_out_layer_.buffer.fence);
+ DLOGI_IF(kTagDriverConfig, "*************************************************************");
+ }
+
+ mdp_commit.release_fence = -1;
+ mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+ if (ioctl_(device_fd_, MSMFB_ATOMIC_COMMIT, &mdp_disp_commit_) < 0) {
+ IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
+ DumpLayerCommit(mdp_disp_commit_);
+ return kErrorHardware;
+ }
+
+ stack->retire_fence_fd = mdp_commit.retire_fence;
+
+ // MDP returns only one release fence for the entire layer stack. Duplicate this fence into all
+ // layers being composed by MDP.
+ for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+ uint32_t layer_index = hw_layer_info.index[i];
+ LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
+ HWRotateInfo *left_rotate = &hw_layers->config[i].rotates[0];
+ HWRotateInfo *right_rotate = &hw_layers->config[i].rotates[1];
+
+ if (!left_rotate->valid && !right_rotate->valid) {
+ input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+ continue;
+ }
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+ if (rotate_info->valid) {
+ input_buffer = &rotate_info->hw_buffer_info.output_buffer;
+ input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+ close_(input_buffer->acquire_fence_fd);
+ input_buffer->acquire_fence_fd = -1;
+ }
+ }
+ }
+ DLOGI_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
+ device_name_);
+ DLOGI_IF(kTagDriverConfig, "retire_fence_fd %d", stack->retire_fence_fd);
+ DLOGI_IF(kTagDriverConfig, "*************************************************************");
+
+ close_(mdp_commit.release_fence);
+
+ return kErrorNone;
+}
+
+DisplayError HWDevice::Flush() {
+ ResetDisplayParams();
+ mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+ mdp_commit.input_layer_cnt = 0;
+ mdp_commit.output_layer = NULL;
+
+ mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+ if (ioctl_(device_fd_, MSMFB_ATOMIC_COMMIT, &mdp_disp_commit_) < 0) {
+ IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
+ DumpLayerCommit(mdp_disp_commit_);
+ return kErrorHardware;
+ }
+ return kErrorNone;
+}
+
+DisplayError HWDevice::SetFormat(const LayerBufferFormat &source, uint32_t *target) {
+ switch (source) {
+ case kFormatARGB8888: *target = MDP_ARGB_8888; break;
+ case kFormatRGBA8888: *target = MDP_RGBA_8888; break;
+ case kFormatBGRA8888: *target = MDP_BGRA_8888; break;
+ case kFormatRGBX8888: *target = MDP_RGBX_8888; break;
+ case kFormatBGRX8888: *target = MDP_BGRX_8888; break;
+ case kFormatRGB888: *target = MDP_RGB_888; break;
+ case kFormatRGB565: *target = MDP_RGB_565; break;
+ case kFormatYCbCr420Planar: *target = MDP_Y_CB_CR_H2V2; break;
+ case kFormatYCrCb420Planar: *target = MDP_Y_CR_CB_H2V2; break;
+ case kFormatYCbCr420SemiPlanar: *target = MDP_Y_CBCR_H2V2; break;
+ case kFormatYCrCb420SemiPlanar: *target = MDP_Y_CRCB_H2V2; break;
+ case kFormatYCbCr422Packed: *target = MDP_YCBYCR_H2V1; break;
+ case kFormatYCbCr420SemiPlanarVenus: *target = MDP_Y_CBCR_H2V2_VENUS; break;
+ case kFormatRGBA8888Ubwc: *target = MDP_RGBA_8888_UBWC; break;
+ case kFormatRGB565Ubwc: *target = MDP_RGB_565_UBWC; break;
+ case kFormatYCbCr420SPVenusUbwc: *target = MDP_Y_CBCR_H2V2_UBWC; break;
+ default:
+ DLOGE("Unsupported format type %d", source);
+ return kErrorParameters;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWDevice::SetStride(HWDeviceType device_type, LayerBufferFormat format,
+ uint32_t width, uint32_t *target) {
+ // TODO(user): This SetStride function is an workaround to satisfy the driver expectation for
+ // rotator and virtual devices. Eventually this will be taken care in the driver.
+ if (device_type != kDeviceRotator && device_type != kDeviceVirtual) {
+ *target = width;
+ return kErrorNone;
+ }
+
+ switch (format) {
+ case kFormatARGB8888:
+ case kFormatRGBA8888:
+ case kFormatBGRA8888:
+ case kFormatRGBX8888:
+ case kFormatBGRX8888:
+ *target = width * 4;
+ break;
+ case kFormatRGB888:
+ *target = width * 3;
+ break;
+ case kFormatRGB565:
+ *target = width * 3;
+ break;
+ case kFormatYCbCr420SemiPlanarVenus:
+ case kFormatYCbCr420SPVenusUbwc:
+ case kFormatYCbCr420Planar:
+ case kFormatYCrCb420Planar:
+ case kFormatYCbCr420SemiPlanar:
+ case kFormatYCrCb420SemiPlanar:
+ *target = width;
+ break;
+ case kFormatYCbCr422Packed:
+ *target = width * 2;
+ break;
+ default:
+ DLOGE("Unsupported format type %d", format);
+ return kErrorParameters;
+ }
+
+ return kErrorNone;
+}
+
+void HWDevice::SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target) {
+ switch (source) {
+ case kBlendingPremultiplied: *target = BLEND_OP_PREMULTIPLIED; break;
+ case kBlendingCoverage: *target = BLEND_OP_COVERAGE; break;
+ default: *target = BLEND_OP_NOT_DEFINED; break;
+ }
+}
+
+void HWDevice::SetRect(const LayerRect &source, mdp_rect *target) {
+ target->x = UINT32(source.left);
+ target->y = UINT32(source.top);
+ target->w = UINT32(source.right) - target->x;
+ target->h = UINT32(source.bottom) - target->y;
+}
+
+void HWDevice::SyncMerge(const int &fd1, const int &fd2, int *target) {
+ if (fd1 >= 0 && fd2 >= 0) {
+ buffer_sync_handler_->SyncMerge(fd1, fd2, target);
+ } else if (fd1 >= 0) {
+ *target = fd1;
+ } else if (fd2 >= 0) {
+ *target = fd2;
+ }
+}
+
+int HWDevice::GetFBNodeIndex(HWDeviceType device_type) {
+ int fb_node_index = -1;
+ for (int i = 0; i < kDeviceMax; i++) {
+ HWPanelInfo *panel_info = new HWPanelInfo();
+ GetHWPanelInfoByNode(i, panel_info);
+ switch (device_type) {
+ case kDevicePrimary:
+ if (panel_info->is_primary_panel) {
+ fb_node_index = i;
+ }
+ break;
+ case kDeviceHDMI:
+ if (panel_info->type == kDTvPanel) {
+ fb_node_index = i;
+ }
+ break;
+ case kDeviceVirtual:
+ if (panel_info->type == kWriteBackPanel) {
+ fb_node_index = i;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return fb_node_index;
+}
+
+void HWDevice::PopulateHWPanelInfo() {
+ panel_info_ = HWPanelInfo();
+ GetHWPanelInfoByNode(fb_node_index_, &panel_info_);
+ DLOGI("Device type = %d, Panel Type = %d, Device Node = %d, Is Primary = %d",
+ device_type_, panel_info_.type, fb_node_index_, panel_info_.is_primary_panel);
+ DLOGI("Partial Update = %d, Dynamic FPS = %d",
+ panel_info_.partial_update, panel_info_.dynamic_fps);
+ DLOGI("Align: left = %d, width = %d, top = %d, height = %d",
+ panel_info_.left_align, panel_info_.width_align,
+ panel_info_.top_align, panel_info_.height_align);
+ DLOGI("ROI: min_width = %d, min_height = %d, need_merge = %d",
+ panel_info_.min_roi_width, panel_info_.min_roi_height, panel_info_.needs_roi_merge);
+ DLOGI("FPS: min = %d, max =%d", panel_info_.min_fps, panel_info_.max_fps);
+ DLOGI("Left Split = %d, Right Split = %d", panel_info_.split_info.left_split,
+ panel_info_.split_info.right_split);
+ DLOGI("Source Split Always = %d", panel_info_.split_info.always_src_split);
+}
+
+void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) {
+ if (!panel_info) {
+ DLOGE("PanelInfo pointer in invalid.");
+ return;
+ }
+ char stringbuffer[kMaxStringLength];
+ FILE *fileptr = NULL;
+ snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_panel_info", fb_path_, device_node);
+ fileptr = fopen(stringbuffer, "r");
+ if (!fileptr) {
+ DLOGW("Failed to open msm_fb_panel_info node device node %d", device_node);
+ return;
+ }
+
+ size_t len = kMaxStringLength;
+ ssize_t read;
+ char *line = stringbuffer;
+ while ((read = getline(&line, &len, fileptr)) != -1) {
+ uint32_t token_count = 0;
+ const uint32_t max_count = 10;
+ char *tokens[max_count] = { NULL };
+ if (!ParseLine(line, tokens, max_count, &token_count)) {
+ if (!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
+ panel_info->partial_update = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "xstart", strlen("xstart"))) {
+ panel_info->left_align = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "walign", strlen("walign"))) {
+ panel_info->width_align = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "ystart", strlen("ystart"))) {
+ panel_info->top_align = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "halign", strlen("halign"))) {
+ panel_info->height_align = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "min_w", strlen("min_w"))) {
+ panel_info->min_roi_width = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "min_h", strlen("min_h"))) {
+ panel_info->min_roi_height = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
+ panel_info->needs_roi_merge = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "dyn_fps_en", strlen("dyn_fps_en"))) {
+ panel_info->dynamic_fps = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
+ panel_info->min_fps = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
+ panel_info->max_fps= atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "primary_panel", strlen("primary_panel"))) {
+ panel_info->is_primary_panel = atoi(tokens[1]);
+ }
+ }
+ }
+ fclose(fileptr);
+ panel_info->type = GetHWPanelType(device_node);
+ GetSplitInfo(device_node, panel_info);
+}
+
+HWPanelType HWDevice::GetHWPanelType(int device_node) {
+ char stringbuffer[kMaxStringLength];
+ DisplayError error = kErrorNone;
+ char *line = stringbuffer;
+ size_t len = kMaxStringLength;
+ ssize_t read;
+ HWPanelType panel_type = kNoPanel;
+
+ snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_type", fb_path_, device_node);
+ FILE *fileptr = fopen(stringbuffer, "r");
+ if (!fileptr) {
+ DLOGW("File not found %s", stringbuffer);
+ return panel_type;
+ }
+ read = getline(&line, &len, fileptr);
+ if (read == -1) {
+ fclose(fileptr);
+ return panel_type;
+ }
+ if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
+ panel_type = kCommandModePanel;
+ } else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) {
+ panel_type = kVideoModePanel;
+ } else if ((strncmp(line, "lvds panel", strlen("lvds panel")) == 0)) {
+ panel_type = kLVDSPanel;
+ } else if ((strncmp(line, "edp panel", strlen("edp panel")) == 0)) {
+ panel_type = kEDPPanel;
+ } else if ((strncmp(line, "dtv panel", strlen("dtv panel")) == 0)) {
+ panel_type = kDTvPanel;
+ } else if ((strncmp(line, "writeback panel", strlen("writeback panel")) == 0)) {
+ panel_type = kWriteBackPanel;
+ }
+ fclose(fileptr);
+
+ return panel_type;
+}
+
+void HWDevice::GetSplitInfo(int device_node, HWPanelInfo *panel_info) {
+ char stringbuffer[kMaxStringLength];
+ FILE *fileptr = NULL;
+ size_t len = kMaxStringLength;
+ ssize_t read;
+ char *line = stringbuffer;
+ uint32_t token_count = 0;
+ const uint32_t max_count = 10;
+ char *tokens[max_count] = { NULL };
+
+ // Split info - for MDSS Version 5 - No need to check version here
+ snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/msm_fb_split", fb_path_, device_node);
+ fileptr = fopen(stringbuffer, "r");
+ if (!fileptr) {
+ DLOGW("File not found %s", stringbuffer);
+ return;
+ }
+
+ // Format "left right" space as delimiter
+ read = getline(&line, &len, fileptr);
+ if (read != -1) {
+ if (!ParseLine(line, tokens, max_count, &token_count)) {
+ panel_info->split_info.left_split = atoi(tokens[0]);
+ panel_info->split_info.right_split = atoi(tokens[1]);
+ }
+ }
+ fclose(fileptr);
+
+ // SourceSplit enabled - Get More information
+ snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/msm_fb_src_split_info", fb_path_,
+ device_node);
+ fileptr = fopen(stringbuffer, "r");
+ if (!fileptr) {
+ DLOGW("File not found %s", stringbuffer);
+ return;
+ }
+
+ read = getline(&line, &len, fileptr);
+ if (read != -1) {
+ if (!strncmp(line, "src_split_always", strlen("src_split_always"))) {
+ panel_info->split_info.always_src_split = true;
+ }
+ }
+ fclose(fileptr);
+}
+
+int HWDevice::ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count) {
+ char *tmp_token = NULL;
+ char *temp_ptr;
+ uint32_t index = 0;
+ const char *delim = ", =\n";
+ if (!input) {
+ return -1;
+ }
+ tmp_token = strtok_r(input, delim, &temp_ptr);
+ while (tmp_token && index < max_token) {
+ tokens[index++] = tmp_token;
+ tmp_token = strtok_r(NULL, delim, &temp_ptr);
+ }
+ *count = index;
+
+ return 0;
+}
+
+bool HWDevice::EnableHotPlugDetection(int enable) {
+ bool ret_value = true;
+ char hpdpath[kMaxStringLength];
+ int hdmi_node_index = GetFBNodeIndex(kDeviceHDMI);
+ snprintf(hpdpath , sizeof(hpdpath), "%s%d/hpd", fb_path_, hdmi_node_index);
+ int hpdfd = open_(hpdpath, O_RDWR, 0);
+ if (hpdfd < 0) {
+ DLOGE("Open failed = %s", hpdpath);
+ return kErrorHardware;
+ }
+ char value = enable ? '1' : '0';
+ ssize_t length = pwrite_(hpdfd, &value, 1, 0);
+ if (length <= 0) {
+ DLOGE("Write failed 'hpd' = %d", enable);
+ ret_value = false;
+ }
+ close_(hpdfd);
+
+ return ret_value;
+}
+
+void HWDevice::ResetDisplayParams() {
+ memset(&mdp_disp_commit_, 0, sizeof(mdp_disp_commit_));
+ memset(&mdp_in_layers_, 0, sizeof(mdp_in_layers_));
+ memset(&mdp_out_layer_, 0, sizeof(mdp_out_layer_));
+ memset(&scale_data_, 0, sizeof(scale_data_));
+
+ for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
+ mdp_in_layers_[i].buffer.fence = -1;
+ }
+
+ mdp_disp_commit_.version = MDP_COMMIT_VERSION_1_0;
+ mdp_disp_commit_.commit_v1.input_layers = mdp_in_layers_;
+ mdp_disp_commit_.commit_v1.output_layer = &mdp_out_layer_;
+ mdp_disp_commit_.commit_v1.release_fence = -1;
+ mdp_disp_commit_.commit_v1.retire_fence = -1;
+}
+
+} // namespace sde
+
diff --git a/displayengine/libs/core/fb/hw_device.h b/displayengine/libs/core/fb/hw_device.h
new file mode 100644
index 0000000..2a240c6
--- /dev/null
+++ b/displayengine/libs/core/fb/hw_device.h
@@ -0,0 +1,127 @@
+/*
+* Copyright (c) 2014 - 2015, 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 __HW_DEVICE_H__
+#define __HW_DEVICE_H__
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/msm_mdp_ext.h>
+#include <video/msm_hdmi_modes.h>
+#include <linux/mdss_rotator.h>
+#include <poll.h>
+#include <pthread.h>
+
+#include "hw_interface.h"
+#include "hw_info_interface.h"
+
+#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, \
+ type, errno, strerror(errno))
+
+namespace sde {
+
+class HWDevice {
+ protected:
+ explicit HWDevice(BufferSyncHandler *buffer_sync_handler);
+ DisplayError Init();
+ DisplayError Open(HWEventHandler *eventhandler);
+ DisplayError Close();
+ DisplayError GetNumDisplayAttributes(uint32_t *count);
+ DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+ uint32_t index);
+ DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
+ DisplayError SetDisplayAttributes(uint32_t index);
+ DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+ DisplayError PowerOn();
+ DisplayError PowerOff();
+ DisplayError Doze();
+ DisplayError Standby();
+ DisplayError Validate(HWLayers *hw_layers);
+ DisplayError Commit(HWLayers *hw_layers);
+ DisplayError Flush();
+
+ enum {
+ kHWEventVSync,
+ kHWEventBlank,
+ };
+
+ static const int kMaxStringLength = 1024;
+ static const int kNumPhysicalDisplays = 2;
+ static const int kNumDisplayEvents = 3;
+
+ void DumpLayerCommit(mdp_layer_commit &layer_commit);
+ DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
+ DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format,
+ uint32_t width, uint32_t *target);
+ void SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target);
+ void SetRect(const LayerRect &source, mdp_rect *target);
+ void SyncMerge(const int &fd1, const int &fd2, int *target);
+
+ // Retrieves HW FrameBuffer Node Index
+ int GetFBNodeIndex(HWDeviceType device_type);
+ // Populates HWPanelInfo based on node index
+ void PopulateHWPanelInfo();
+ void GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info);
+ HWPanelType GetHWPanelType(int device_node);
+ void GetSplitInfo(int device_node, HWPanelInfo *panel_info);
+ int ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count);
+ mdp_scale_data* GetScaleDataRef(uint32_t index) { return &scale_data_[index]; }
+ void ResetDisplayParams();
+
+ bool EnableHotPlugDetection(int enable);
+
+ // Pointers to system calls which are either mapped to actual system call or virtual driver.
+ int (*ioctl_)(int, int, ...);
+ int (*open_)(const char *, int, ...);
+ int (*close_)(int);
+ int (*poll_)(struct pollfd *, nfds_t, int);
+ ssize_t (*pread_)(int, void *, size_t, off_t);
+ ssize_t (*pwrite_)(int, const void *, size_t, off_t);
+ FILE* (*fopen_)( const char *fname, const char *mode);
+ int (*fclose_)(FILE* fileptr);
+ ssize_t (*getline_)(char **lineptr, size_t *linelen, FILE *stream);
+
+ // Store the Device EventHandler - used for callback
+ HWEventHandler *event_handler_;
+ HWResourceInfo hw_resource_;
+ HWPanelInfo panel_info_;
+ HWInfoInterface *hw_info_intf_;
+ int fb_node_index_;
+ const char *fb_path_;
+ bool hotplug_enabled_;
+ BufferSyncHandler *buffer_sync_handler_;
+ int device_fd_;
+ HWDeviceType device_type_;
+ mdp_layer_commit mdp_disp_commit_;
+ mdp_input_layer mdp_in_layers_[kMaxSDELayers * 2]; // split panel (left + right)
+ mdp_scale_data scale_data_[kMaxSDELayers * 2];
+ mdp_output_layer mdp_out_layer_;
+ const char *device_name_;
+};
+
+} // namespace sde
+
+#endif // __HW_DEVICE_H__
+
diff --git a/displayengine/libs/core/fb/hw_hdmi.cpp b/displayengine/libs/core/fb/hw_hdmi.cpp
new file mode 100644
index 0000000..bc97cf6
--- /dev/null
+++ b/displayengine/libs/core/fb/hw_hdmi.cpp
@@ -0,0 +1,336 @@
+/*
+* Copyright (c) 2015, 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 <sys/ioctl.h>
+#include <ctype.h>
+#include <utils/debug.h>
+#include <fcntl.h>
+#include "hw_hdmi.h"
+
+#define __CLASS__ "HWHDMI"
+
+namespace sde {
+
+static int ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count) {
+ char *tmp_token = NULL;
+ char *temp_ptr;
+ uint32_t index = 0;
+ const char *delim = ", =\n";
+ if (!input) {
+ return -1;
+ }
+ tmp_token = strtok_r(input, delim, &temp_ptr);
+ while (tmp_token && index < max_token) {
+ tokens[index++] = tmp_token;
+ tmp_token = strtok_r(NULL, delim, &temp_ptr);
+ }
+ *count = index;
+
+ return 0;
+}
+
+static bool MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode,
+ fb_var_screeninfo *info) {
+ if (!mode || !info) {
+ return false;
+ }
+
+ info->reserved[0] = 0;
+ info->reserved[1] = 0;
+ info->reserved[2] = 0;
+ info->reserved[3] = (info->reserved[3] & 0xFFFF) | (mode->video_format << 16);
+ info->xoffset = 0;
+ info->yoffset = 0;
+ info->xres = mode->active_h;
+ info->yres = mode->active_v;
+ info->pixclock = (mode->pixel_freq) * 1000;
+ info->vmode = mode->interlaced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
+ info->right_margin = mode->front_porch_h;
+ info->hsync_len = mode->pulse_width_h;
+ info->left_margin = mode->back_porch_h;
+ info->lower_margin = mode->front_porch_v;
+ info->vsync_len = mode->pulse_width_v;
+ info->upper_margin = mode->back_porch_v;
+
+ return true;
+}
+
+DisplayError HWHDMIInterface::Create(HWHDMIInterface **intf, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler) {
+ DisplayError error = kErrorNone;
+ HWHDMI *hw_fb_hdmi = NULL;
+
+ hw_fb_hdmi = new HWHDMI(buffer_sync_handler, hw_info_intf);
+ error = hw_fb_hdmi->Init();
+ if (error != kErrorNone) {
+ delete hw_fb_hdmi;
+ } else {
+ *intf = hw_fb_hdmi;
+ }
+ return error;
+}
+
+DisplayError HWHDMIInterface::Destroy(HWHDMIInterface *intf) {
+ HWHDMI *hw_fb_hdmi = static_cast<HWHDMI *>(intf);
+ hw_fb_hdmi->Deinit();
+ delete hw_fb_hdmi;
+
+ return kErrorNone;
+}
+
+HWHDMI::HWHDMI(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
+ : HWDevice(buffer_sync_handler) {
+ HWDevice::device_type_ = kDeviceHDMI;
+ HWDevice::device_name_ = "HDMI Display Device";
+ HWDevice::hw_info_intf_ = hw_info_intf;
+}
+
+DisplayError HWHDMI::Init() {
+ DisplayError error = kErrorNone;
+
+ error = HWDevice::Init();
+ if (error != kErrorNone) {
+ goto CleanupOnError;
+ }
+
+ // Mode look-up table for HDMI
+ supported_video_modes_ = new msm_hdmi_mode_timing_info[HDMI_VFRMT_MAX];
+ if (!supported_video_modes_) {
+ error = kErrorMemory;
+ goto CleanupOnError;
+ }
+ // Populate the mode table for supported modes
+ MSM_HDMI_MODES_INIT_TIMINGS(supported_video_modes_);
+ MSM_HDMI_MODES_SET_SUPP_TIMINGS(supported_video_modes_, MSM_HDMI_MODES_ALL);
+
+ return kErrorNone;
+
+CleanupOnError:
+ if (supported_video_modes_) {
+ delete supported_video_modes_;
+ }
+
+ return error;
+}
+
+DisplayError HWHDMI::Deinit() {
+ hdmi_mode_count_ = 0;
+ if (supported_video_modes_) {
+ delete supported_video_modes_;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::Open(HWEventHandler *eventhandler) {
+ return HWDevice::Open(eventhandler);
+}
+
+DisplayError HWHDMI::Close() {
+ return HWDevice::Close();
+}
+
+DisplayError HWHDMI::GetNumDisplayAttributes(uint32_t *count) {
+ *count = GetHDMIModeCount();
+ if (*count <= 0) {
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+int HWHDMI::GetHDMIModeCount() {
+ ssize_t length = -1;
+ char edid_str[256] = {'\0'};
+ char edid_path[kMaxStringLength] = {'\0'};
+ snprintf(edid_path, sizeof(edid_path), "%s%d/edid_modes", fb_path_, fb_node_index_);
+ int edid_file = open_(edid_path, O_RDONLY);
+ if (edid_file < 0) {
+ DLOGE("EDID file open failed.");
+ return -1;
+ }
+
+ length = pread_(edid_file, edid_str, sizeof(edid_str)-1, 0);
+ if (length <= 0) {
+ DLOGE("%s: edid_modes file empty");
+ edid_str[0] = '\0';
+ } else {
+ DLOGI("EDID mode string: %s", edid_str);
+ while (length > 1 && isspace(edid_str[length-1])) {
+ --length;
+ }
+ edid_str[length] = '\0';
+ }
+ close_(edid_file);
+
+ if (length > 0) {
+ // Get EDID modes from the EDID string
+ char *ptr = edid_str;
+ const uint32_t edid_count_max = 128;
+ char *tokens[edid_count_max] = { NULL };
+ ParseLine(ptr, tokens, edid_count_max, &hdmi_mode_count_);
+ for (uint32_t i = 0; i < hdmi_mode_count_; i++) {
+ hdmi_modes_[i] = atoi(tokens[i]);
+ }
+ }
+ return (hdmi_mode_count_ > 0) ? hdmi_mode_count_ : 0;
+}
+
+DisplayError HWHDMI::GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+ uint32_t index) {
+ DTRACE_SCOPED();
+
+ // Variable screen info
+ STRUCT_VAR(fb_var_screeninfo, var_screeninfo);
+
+ // Get the resolution info from the look up table
+ msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[0];
+ for (int i = 0; i < HDMI_VFRMT_MAX; i++) {
+ msm_hdmi_mode_timing_info *cur = &supported_video_modes_[i];
+ if (cur->video_format == hdmi_modes_[index]) {
+ timing_mode = cur;
+ break;
+ }
+ }
+ display_attributes->x_pixels = timing_mode->active_h;
+ display_attributes->y_pixels = timing_mode->active_v;
+ display_attributes->v_total = timing_mode->active_v + timing_mode->front_porch_v +
+ 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) / 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) {
+ display_attributes->is_device_split = true;
+ display_attributes->split_left = display_attributes->x_pixels / 2;
+ }
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::SetDisplayAttributes(uint32_t index) {
+ DTRACE_SCOPED();
+
+ DisplayError error = kErrorNone;
+
+ // Variable screen info
+ STRUCT_VAR(fb_var_screeninfo, vscreeninfo);
+ if (ioctl_(device_fd_, FBIOGET_VSCREENINFO, &vscreeninfo) < 0) {
+ IOCTL_LOGE(FBIOGET_VSCREENINFO, device_type_);
+ return kErrorHardware;
+ }
+
+ DLOGI("GetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3],
+ vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
+ vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
+ vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
+
+ msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[0];
+ for (int i = 0; i < HDMI_VFRMT_MAX; i++) {
+ msm_hdmi_mode_timing_info *cur = &supported_video_modes_[i];
+ if (cur->video_format == hdmi_modes_[index]) {
+ timing_mode = cur;
+ break;
+ }
+ }
+
+ if (MapHDMIDisplayTiming(timing_mode, &vscreeninfo) == false) {
+ return kErrorParameters;
+ }
+
+ STRUCT_VAR(msmfb_metadata, metadata);
+ metadata.op = metadata_op_vic;
+ metadata.data.video_info_code = timing_mode->video_format;
+ if (ioctl(device_fd_, MSMFB_METADATA_SET, &metadata) < 0) {
+ IOCTL_LOGE(MSMFB_METADATA_SET, device_type_);
+ return kErrorHardware;
+ }
+
+ DLOGI("SetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3] & 0xFF00,
+ vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
+ vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
+ vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
+
+ vscreeninfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
+ if (ioctl_(device_fd_, FBIOPUT_VSCREENINFO, &vscreeninfo) < 0) {
+ IOCTL_LOGE(FBIOGET_VSCREENINFO, device_type_);
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::GetConfigIndex(uint32_t mode, uint32_t *index) {
+ // Check if the mode is valid and return corresponding index
+ for (uint32_t i = 0; i < hdmi_mode_count_; i++) {
+ if (hdmi_modes_[i] == mode) {
+ *index = i;
+ DLOGI("Index = %d for config = %d", *index, mode);
+ return kErrorNone;
+ }
+ }
+
+ DLOGE("Config = %d not supported", mode);
+ return kErrorNotSupported;
+}
+
+DisplayError HWHDMI::PowerOn() {
+ return HWDevice::PowerOn();
+}
+
+DisplayError HWHDMI::PowerOff() {
+ return HWDevice::PowerOff();
+}
+
+DisplayError HWHDMI::Doze() {
+ return HWDevice::Doze();
+}
+
+DisplayError HWHDMI::Standby() {
+ return HWDevice::Standby();
+}
+
+DisplayError HWHDMI::Validate(HWLayers *hw_layers) {
+ return HWDevice::Validate(hw_layers);
+}
+
+DisplayError HWHDMI::Commit(HWLayers *hw_layers) {
+ return HWDevice::Commit(hw_layers);
+}
+
+DisplayError HWHDMI::Flush() {
+ return HWDevice::Flush();
+}
+
+DisplayError HWHDMI::GetHWPanelInfo(HWPanelInfo *panel_info) {
+ return HWDevice::GetHWPanelInfo(panel_info);
+}
+
+} // namespace sde
+
diff --git a/displayengine/libs/core/fb/hw_hdmi.h b/displayengine/libs/core/fb/hw_hdmi.h
new file mode 100644
index 0000000..8fc3c47
--- /dev/null
+++ b/displayengine/libs/core/fb/hw_hdmi.h
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2015, 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 __HW_HDMI_H__
+#define __HW_HDMI_H__
+
+#include "hw_device.h"
+#include "hw_hdmi_interface.h"
+
+namespace sde {
+
+class HWHDMI : public HWDevice, public HWHDMIInterface {
+ public:
+ HWHDMI(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
+ virtual DisplayError Init();
+ virtual DisplayError Deinit();
+ virtual DisplayError Open(HWEventHandler *eventhandler);
+ virtual DisplayError Close();
+ virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+ virtual DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+ uint32_t index);
+ virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
+ virtual DisplayError SetDisplayAttributes(uint32_t index);
+ virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+ virtual DisplayError PowerOn();
+ virtual DisplayError PowerOff();
+ virtual DisplayError Doze();
+ virtual DisplayError Standby();
+ virtual DisplayError Validate(HWLayers *hw_layers);
+ virtual DisplayError Commit(HWLayers *hw_layers);
+ virtual DisplayError Flush();
+
+ private:
+ int GetHDMIModeCount();
+
+ uint32_t hdmi_mode_count_;
+ uint32_t hdmi_modes_[256];
+ // Holds the hdmi timing information. Ex: resolution, fps etc.,
+ msm_hdmi_mode_timing_info *supported_video_modes_;
+};
+
+} // namespace sde
+
+#endif // __HW_HDMI_H__
+
diff --git a/displayengine/libs/core/fb/hw_info.cpp b/displayengine/libs/core/fb/hw_info.cpp
new file mode 100644
index 0000000..cddb590
--- /dev/null
+++ b/displayengine/libs/core/fb/hw_info.cpp
@@ -0,0 +1,171 @@
+/*
+* Copyright (c) 2015, 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 "hw_info.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+
+#define __CLASS__ "HWInfo"
+
+namespace sde {
+
+int HWInfo::ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count) {
+ char *tmp_token = NULL;
+ char *temp_ptr;
+ uint32_t index = 0;
+ const char *delim = ", =\n";
+ if (!input) {
+ return -1;
+ }
+ tmp_token = strtok_r(input, delim, &temp_ptr);
+ while (tmp_token && index < max_token) {
+ tokens[index++] = tmp_token;
+ tmp_token = strtok_r(NULL, delim, &temp_ptr);
+ }
+ *count = index;
+
+ return 0;
+}
+
+DisplayError HWInfoInterface::Create(HWInfoInterface **intf) {
+ DisplayError error = kErrorNone;
+ HWInfo *hw_info = NULL;
+
+ hw_info = new HWInfo();
+ if (!hw_info) {
+ error = kErrorMemory;
+ } else {
+ *intf = hw_info;
+ }
+
+ return error;
+}
+
+DisplayError HWInfoInterface::Destroy(HWInfoInterface *intf) {
+ HWInfo *hw_info = static_cast<HWInfo *>(intf);
+ delete hw_info;
+
+ return kErrorNone;
+}
+
+DisplayError HWInfo::GetHWResourceInfo(HWResourceInfo *hw_resource) {
+ if (!hw_resource) {
+ DLOGE("HWResourceInfo pointer in invalid.");
+ return kErrorParameters;
+ }
+ const char *kHWCapabilitiesPath = "/sys/devices/virtual/graphics/fb";
+ FILE *fileptr = NULL;
+ char stringbuffer[kMaxStringLength];
+ uint32_t token_count = 0;
+ const uint32_t max_count = 10;
+ char *tokens[max_count] = { NULL };
+ snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/mdp/caps",
+ kHWCapabilitiesPath, kHWCapabilitiesNode);
+ fileptr = fopen(stringbuffer, "rb");
+
+ if (!fileptr) {
+ DLOGE("File '%s' not found", stringbuffer);
+ return kErrorHardware;
+ }
+
+ size_t len = kMaxStringLength;
+ ssize_t read;
+ char *line = stringbuffer;
+ hw_resource->hw_version = kHWMdssVersion5;
+ while ((read = getline(&line, &len, fileptr)) != -1) {
+ // parse the line and update information accordingly
+ if (!ParseLine(line, tokens, max_count, &token_count)) {
+ if (!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
+ hw_resource->hw_revision = atoi(tokens[1]); // HW Rev, v1/v2
+ } else if (!strncmp(tokens[0], "rgb_pipes", strlen("rgb_pipes"))) {
+ hw_resource->num_rgb_pipe = UINT8(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "vig_pipes", strlen("vig_pipes"))) {
+ hw_resource->num_vig_pipe = UINT8(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
+ hw_resource->num_dma_pipe = UINT8(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "cursor_pipes", strlen("cursor_pipes"))) {
+ hw_resource->num_cursor_pipe = UINT8(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "blending_stages", strlen("blending_stages"))) {
+ hw_resource->num_blending_stages = UINT8(atoi(tokens[1]));
+ } else if (!strncmp(tokens[0], "max_downscale_ratio", strlen("max_downscale_ratio"))) {
+ hw_resource->max_scale_down = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "max_upscale_ratio", strlen("max_upscale_ratio"))) {
+ hw_resource->max_scale_up = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "max_bandwidth_low", strlen("max_bandwidth_low"))) {
+ hw_resource->max_bandwidth_low = atol(tokens[1]);
+ } else if (!strncmp(tokens[0], "max_bandwidth_high", strlen("max_bandwidth_high"))) {
+ hw_resource->max_bandwidth_high = atol(tokens[1]);
+ } else if (!strncmp(tokens[0], "max_mixer_width", strlen("max_mixer_width"))) {
+ hw_resource->max_mixer_width = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "max_pipe_bw", strlen("max_pipe_bw"))) {
+ hw_resource->max_pipe_bw = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "max_mdp_clk", strlen("max_mdp_clk"))) {
+ hw_resource->max_sde_clk = atoi(tokens[1]);
+ } else if (!strncmp(tokens[0], "clk_fudge_factor", strlen("clk_fudge_factor"))) {
+ hw_resource->clk_fudge_factor = FLOAT(atoi(tokens[1])) / FLOAT(atoi(tokens[2]));
+ } else if (!strncmp(tokens[0], "features", strlen("features"))) {
+ for (uint32_t i = 0; i < token_count; i++) {
+ if (!strncmp(tokens[i], "bwc", strlen("bwc"))) {
+ hw_resource->has_bwc = true;
+ } else if (!strncmp(tokens[i], "decimation", strlen("decimation"))) {
+ hw_resource->has_decimation = true;
+ } else if (!strncmp(tokens[i], "tile_format", strlen("tile_format"))) {
+ hw_resource->has_macrotile = true;
+ } else if (!strncmp(tokens[i], "src_split", strlen("src_split"))) {
+ hw_resource->is_src_split = true;
+ } else if (!strncmp(tokens[i], "non_scalar_rgb", strlen("non_scalar_rgb"))) {
+ hw_resource->has_non_scalar_rgb = true;
+ } else if (!strncmp(tokens[i], "rotator_downscale", strlen("rotator_downscale"))) {
+ hw_resource->has_rotator_downscale = true;
+ }
+ }
+ }
+ }
+ }
+ fclose(fileptr);
+
+ DLOGI("SDE Version = %d, SDE Revision = %x, RGB = %d, VIG = %d, DMA = %d, Cursor = %d",
+ hw_resource->hw_version, hw_resource->hw_revision, hw_resource->num_rgb_pipe,
+ hw_resource->num_vig_pipe, hw_resource->num_dma_pipe, hw_resource->num_cursor_pipe);
+ DLOGI("Upscale Ratio = %d, Downscale Ratio = %d, Blending Stages = %d", hw_resource->max_scale_up,
+ hw_resource->max_scale_down, hw_resource->num_blending_stages);
+ DLOGI("BWC = %d, Decimation = %d, Tile Format = %d, Rotator Downscale = %d", hw_resource->has_bwc,
+ hw_resource->has_decimation, hw_resource->has_macrotile,
+ hw_resource->has_rotator_downscale);
+ DLOGI("SourceSplit = %d", hw_resource->is_src_split);
+ DLOGI("MaxLowBw = %"PRIu64", MaxHighBw = %"PRIu64"", hw_resource->max_bandwidth_low,
+ hw_resource->max_bandwidth_high);
+ DLOGI("MaxPipeBw = %"PRIu64" KBps, MaxSDEClock = %"PRIu64" Hz, ClockFudgeFactor = %f",
+ hw_resource->max_pipe_bw, hw_resource->max_sde_clk, hw_resource->clk_fudge_factor);
+
+ return kErrorNone;
+}
+
+} // namespace sde
+
diff --git a/displayengine/libs/core/hw_interface.cpp b/displayengine/libs/core/fb/hw_info.h
similarity index 63%
copy from displayengine/libs/core/hw_interface.cpp
copy to displayengine/libs/core/fb/hw_info.h
index 6b99a73..31667ae 100644
--- a/displayengine/libs/core/hw_interface.cpp
+++ b/displayengine/libs/core/fb/hw_info.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015, 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:
@@ -22,34 +22,33 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <utils/constants.h>
+#ifndef __HW_INFO_H__
+#define __HW_INFO_H__
-#include "hw_interface.h"
-#include "hw_framebuffer.h"
+#include <inttypes.h>
+#include <core/sde_types.h>
+#include <private/hw_info_types.h>
+#include "hw_info_interface.h"
namespace sde {
-DisplayError HWInterface::Create(HWInterface **intf, BufferSyncHandler *buffer_sync_handler) {
- DisplayError error = kErrorNone;
- HWFrameBuffer *hw_frame_buffer = NULL;
+class HWInfo: public HWInfoInterface {
+ public:
+ virtual DisplayError GetHWResourceInfo(HWResourceInfo *hw_resource);
- hw_frame_buffer = new HWFrameBuffer(buffer_sync_handler);
- error = hw_frame_buffer->Init();
- if (UNLIKELY(error != kErrorNone)) {
- delete hw_frame_buffer;
- } else {
- *intf = hw_frame_buffer;
- }
+ private:
+ // TODO(user): Read Mdss version from the driver
+ static const int kHWMdssVersion5 = 500; // MDSS_V5
+ static const int kMaxStringLength = 1024;
+ // MDP Capabilities are replicated across all frame buffer devices.
+ // However, we rely on reading the capabalities from fbO since this
+ // is guaranteed to be available.
+ static const int kHWCapabilitiesNode = 0;
- return error;
-}
-
-DisplayError HWInterface::Destroy(HWInterface *intf) {
- HWFrameBuffer *hw_frame_buffer = static_cast<HWFrameBuffer *>(intf);
- hw_frame_buffer->Deinit();
- delete hw_frame_buffer;
- return kErrorNone;
-}
+ static int ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count);
+};
} // namespace sde
+#endif // __HW_INFO_H__
+
diff --git a/displayengine/libs/core/fb/hw_primary.cpp b/displayengine/libs/core/fb/hw_primary.cpp
new file mode 100644
index 0000000..0dd0db2
--- /dev/null
+++ b/displayengine/libs/core/fb/hw_primary.cpp
@@ -0,0 +1,372 @@
+/*
+* Copyright (c) 2015, 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 <sys/prctl.h>
+#include <sys/ioctl.h>
+#include <pthread.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <utils/debug.h>
+#include "hw_primary.h"
+
+#define __CLASS__ "HWPrimary"
+
+namespace sde {
+
+DisplayError HWPrimaryInterface::Create(HWPrimaryInterface **intf, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler) {
+ DisplayError error = kErrorNone;
+ HWPrimary *hw_primary = NULL;
+
+ hw_primary = new HWPrimary(buffer_sync_handler, hw_info_intf);
+ error = hw_primary->Init();
+ if (error != kErrorNone) {
+ delete hw_primary;
+ } else {
+ *intf = hw_primary;
+ }
+
+ return error;
+}
+
+DisplayError HWPrimaryInterface::Destroy(HWPrimaryInterface *intf) {
+ HWPrimary *hw_primary = static_cast<HWPrimary *>(intf);
+ hw_primary->Deinit();
+ delete hw_primary;
+
+ return kErrorNone;
+}
+
+HWPrimary::HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
+ : HWDevice(buffer_sync_handler), event_thread_name_("SDE_EventThread"), fake_vsync_(false),
+ exit_threads_(false) {
+ HWDevice::device_type_ = kDevicePrimary;
+ HWDevice::device_name_ = "Primary Display Device";
+ HWDevice::hw_info_intf_ = hw_info_intf;
+}
+
+DisplayError HWPrimary::Init() {
+ DisplayError error = kErrorNone;
+ char node_path[kMaxStringLength] = {0};
+ char data[kMaxStringLength] = {0};
+ const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify"};
+
+ error = HWDevice::Init();
+ if (error != kErrorNone) {
+ goto CleanupOnError;
+ }
+
+ // Open nodes for polling
+ for (int event = 0; event < kNumDisplayEvents; event++) {
+ poll_fds_[event].fd = -1;
+ }
+
+ if (!fake_vsync_) {
+ for (int event = 0; event < kNumDisplayEvents; event++) {
+ pollfd &poll_fd = poll_fds_[event];
+
+ if ((panel_info_.type == kCommandModePanel) &&
+ (!strncmp(event_name[event], "idle_notify", strlen("idle_notify")))) {
+ continue;
+ }
+
+ snprintf(node_path, sizeof(node_path), "%s%d/%s", fb_path_, fb_node_index_,
+ event_name[event]);
+
+ poll_fd.fd = open_(node_path, O_RDONLY);
+ if (poll_fd.fd < 0) {
+ DLOGE("open failed for event=%d, error=%s", event, strerror(errno));
+ error = kErrorHardware;
+ goto CleanupOnError;
+ }
+
+ // Read once on all fds to clear data on all fds.
+ pread_(poll_fd.fd, data , kMaxStringLength, 0);
+ poll_fd.events = POLLPRI | POLLERR;
+ }
+ }
+
+ // Start the Event thread
+ if (pthread_create(&event_thread_, NULL, &DisplayEventThread, this) < 0) {
+ DLOGE("Failed to start %s, error = %s", event_thread_name_);
+ error = kErrorResources;
+ goto CleanupOnError;
+ }
+
+ // Disable HPD at start if HDMI is external, it will be enabled later when the display powers on
+ // This helps for framework reboot or adb shell stop/start
+ EnableHotPlugDetection(0);
+
+ return kErrorNone;
+
+CleanupOnError:
+ // Close all poll fds
+ for (int event = 0; event < kNumDisplayEvents; event++) {
+ int &fd = poll_fds_[event].fd;
+ if (fd >= 0) {
+ close_(fd);
+ }
+ }
+
+ return error;
+}
+
+DisplayError HWPrimary::Deinit() {
+ exit_threads_ = true;
+ pthread_join(event_thread_, NULL);
+
+ for (int event = 0; event < kNumDisplayEvents; event++) {
+ close_(poll_fds_[event].fd);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::Open(HWEventHandler *eventhandler) {
+ return HWDevice::Open(eventhandler);
+}
+
+DisplayError HWPrimary::Close() {
+ return HWDevice::Close();
+}
+
+DisplayError HWPrimary::GetNumDisplayAttributes(uint32_t *count) {
+ return HWDevice::GetNumDisplayAttributes(count);
+}
+
+DisplayError HWPrimary::GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+ uint32_t index) {
+ DTRACE_SCOPED();
+
+ // Variable screen info
+ STRUCT_VAR(fb_var_screeninfo, var_screeninfo);
+
+ if (ioctl_(device_fd_, FBIOGET_VSCREENINFO, &var_screeninfo) < 0) {
+ IOCTL_LOGE(FBIOGET_VSCREENINFO, device_type_);
+ return kErrorHardware;
+ }
+
+ // Frame rate
+ STRUCT_VAR(msmfb_metadata, meta_data);
+ meta_data.op = metadata_op_frame_rate;
+ if (ioctl_(device_fd_, MSMFB_METADATA_GET, &meta_data) < 0) {
+ IOCTL_LOGE(MSMFB_METADATA_GET, device_type_);
+ return kErrorHardware;
+ }
+
+ // If driver doesn't return width/height information, default to 160 dpi
+ if (INT(var_screeninfo.width) <= 0 || INT(var_screeninfo.height) <= 0) {
+ var_screeninfo.width = INT(((FLOAT(var_screeninfo.xres) * 25.4f)/160.0f) + 0.5f);
+ var_screeninfo.height = INT(((FLOAT(var_screeninfo.yres) * 25.4f)/160.0f) + 0.5f);
+ }
+
+ display_attributes->x_pixels = var_screeninfo.xres;
+ display_attributes->y_pixels = var_screeninfo.yres;
+ display_attributes->v_total = var_screeninfo.yres + var_screeninfo.lower_margin +
+ var_screeninfo.upper_margin + var_screeninfo.vsync_len;
+ display_attributes->x_dpi =
+ (FLOAT(var_screeninfo.xres) * 25.4f) / FLOAT(var_screeninfo.width);
+ display_attributes->y_dpi =
+ (FLOAT(var_screeninfo.yres) * 25.4f) / FLOAT(var_screeninfo.height);
+ display_attributes->fps = FLOAT(meta_data.data.panel_frame_rate);
+ display_attributes->vsync_period_ns = UINT32(1000000000L / display_attributes->fps);
+ display_attributes->is_device_split = (panel_info_.split_info.left_split ||
+ (var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false;
+ display_attributes->split_left = panel_info_.split_info.left_split ?
+ panel_info_.split_info.left_split : display_attributes->x_pixels / 2;
+ display_attributes->always_src_split = panel_info_.split_info.always_src_split;
+
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::SetDisplayAttributes(uint32_t index) {
+ return HWDevice::SetDisplayAttributes(index);
+}
+
+DisplayError HWPrimary::GetConfigIndex(uint32_t mode, uint32_t *index) {
+ return HWDevice::GetConfigIndex(mode, index);
+}
+
+DisplayError HWPrimary::PowerOn() {
+ return HWDevice::PowerOn();
+}
+
+DisplayError HWPrimary::PowerOff() {
+ if (ioctl_(device_fd_, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
+ IOCTL_LOGE(FB_BLANK_POWERDOWN, device_type_);
+ return kErrorHardware;
+ }
+ return kErrorNone;
+}
+
+DisplayError HWPrimary::Doze() {
+ return HWDevice::Doze();
+}
+
+DisplayError HWPrimary::Standby() {
+ return HWDevice::Standby();
+}
+
+DisplayError HWPrimary::Validate(HWLayers *hw_layers) {
+ return HWDevice::Validate(hw_layers);
+}
+
+DisplayError HWPrimary::Commit(HWLayers *hw_layers) {
+ return HWDevice::Commit(hw_layers);
+}
+
+DisplayError HWPrimary::Flush() {
+ return HWDevice::Flush();
+}
+
+DisplayError HWPrimary::GetHWPanelInfo(HWPanelInfo *panel_info) {
+ return HWDevice::GetHWPanelInfo(panel_info);
+}
+
+void* HWPrimary::DisplayEventThread(void *context) {
+ if (context) {
+ return reinterpret_cast<HWPrimary *>(context)->DisplayEventThreadHandler();
+ }
+
+ return NULL;
+}
+
+void* HWPrimary::DisplayEventThreadHandler() {
+ char data[kMaxStringLength] = {0};
+
+ prctl(PR_SET_NAME, event_thread_name_, 0, 0, 0);
+ setpriority(PRIO_PROCESS, 0, kThreadPriorityUrgent);
+
+ if (fake_vsync_) {
+ while (!exit_threads_) {
+ // Fake vsync is used only when set explicitly through a property(todo) or when
+ // the vsync timestamp node cannot be opened at bootup. There is no
+ // fallback to fake vsync from the true vsync loop, ever, as the
+ // condition can easily escape detection.
+ // Also, fake vsync is delivered only for the primary display.
+ usleep(16666);
+ STRUCT_VAR(timeval, time_now);
+ gettimeofday(&time_now, NULL);
+ uint64_t ts = uint64_t(time_now.tv_sec)*1000000000LL +uint64_t(time_now.tv_usec)*1000LL;
+
+ // Send Vsync event for primary display(0)
+ event_handler_->VSync(ts);
+ }
+
+ pthread_exit(0);
+ }
+
+ typedef void (HWPrimary::*EventHandler)(char*);
+ EventHandler event_handler[kNumDisplayEvents] = { &HWPrimary::HandleVSync,
+ &HWPrimary::HandleBlank,
+ &HWPrimary::HandleIdleTimeout };
+
+ while (!exit_threads_) {
+ int error = poll_(poll_fds_, kNumDisplayEvents, -1);
+ if (error < 0) {
+ DLOGW("poll failed. error = %s", strerror(errno));
+ continue;
+ }
+ for (int event = 0; event < kNumDisplayEvents; event++) {
+ pollfd &poll_fd = poll_fds_[event];
+
+ if (poll_fd.revents & POLLPRI) {
+ ssize_t length = pread_(poll_fd.fd, data, kMaxStringLength, 0);
+ if (length < 0) {
+ // If the read was interrupted - it is not a fatal error, just continue.
+ DLOGW("pread failed. event = %d, error = %s", event, strerror(errno));
+ continue;
+ }
+
+ (this->*event_handler[event])(data);
+ }
+ }
+ }
+
+ pthread_exit(0);
+
+ return NULL;
+}
+
+void HWPrimary::HandleVSync(char *data) {
+ int64_t timestamp = 0;
+ if (!strncmp(data, "VSYNC=", strlen("VSYNC="))) {
+ timestamp = strtoull(data + strlen("VSYNC="), NULL, 0);
+ }
+ event_handler_->VSync(timestamp);
+}
+
+void HWPrimary::HandleBlank(char *data) {
+ // TODO(user): Need to send blank Event
+}
+
+void HWPrimary::HandleIdleTimeout(char *data) {
+ event_handler_->IdleTimeout();
+}
+
+void HWPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+ char node_path[kMaxStringLength] = {0};
+
+ DLOGI("Setting idle timeout to = %d ms", timeout_ms);
+
+ snprintf(node_path, sizeof(node_path), "%s%d/idle_time", fb_path_, fb_node_index_);
+
+ // Open a sysfs node to send the timeout value to driver.
+ int fd = open_(node_path, O_WRONLY);
+ if (fd < 0) {
+ DLOGE("Unable to open %s, node %s", node_path, strerror(errno));
+ return;
+ }
+
+ char timeout_string[64];
+ snprintf(timeout_string, sizeof(timeout_string), "%d", timeout_ms);
+
+ // Notify driver about the timeout value
+ ssize_t length = pwrite_(fd, timeout_string, strlen(timeout_string), 0);
+ if (length < -1) {
+ DLOGE("Unable to write into %s, node %s", node_path, strerror(errno));
+ }
+
+ close_(fd);
+}
+
+DisplayError HWPrimary::SetVSyncState(bool enable) {
+ DTRACE_SCOPED();
+
+ int vsync_on = enable ? 1 : 0;
+ if (ioctl_(device_fd_, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) < 0) {
+ IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, device_type_);
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+} // namespace sde
+
diff --git a/displayengine/libs/core/fb/hw_primary.h b/displayengine/libs/core/fb/hw_primary.h
new file mode 100644
index 0000000..8ede12d
--- /dev/null
+++ b/displayengine/libs/core/fb/hw_primary.h
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2015, 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 __HW_PRIMARY_H__
+#define __HW_PRIMARY_H__
+
+#include "hw_device.h"
+#include "hw_primary_interface.h"
+
+namespace sde {
+
+class HWPrimary : public HWDevice, public HWPrimaryInterface {
+ public:
+ HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
+ virtual DisplayError Init();
+ virtual DisplayError Deinit();
+ virtual DisplayError Open(HWEventHandler *eventhandler);
+ virtual DisplayError Close();
+ virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+ virtual DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+ uint32_t index);
+ virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
+ virtual DisplayError SetDisplayAttributes(uint32_t index);
+ virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+ virtual DisplayError PowerOn();
+ virtual DisplayError PowerOff();
+ virtual DisplayError Doze();
+ virtual DisplayError Standby();
+ virtual DisplayError Validate(HWLayers *hw_layers);
+ virtual DisplayError Commit(HWLayers *hw_layers);
+ virtual DisplayError Flush();
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+ virtual DisplayError SetVSyncState(bool enable);
+
+ private:
+ // Event Thread to receive vsync/blank events
+ static void* DisplayEventThread(void *context);
+ void* DisplayEventThreadHandler();
+
+ void HandleVSync(char *data);
+ void HandleBlank(char *data);
+ void HandleIdleTimeout(char *data);
+
+ pollfd poll_fds_[kNumDisplayEvents];
+ pthread_t event_thread_;
+ const char *event_thread_name_;
+ bool fake_vsync_;
+ bool exit_threads_;
+};
+
+} // namespace sde
+
+#endif // __HW_PRIMARY_H__
+
diff --git a/displayengine/libs/core/fb/hw_rotator.cpp b/displayengine/libs/core/fb/hw_rotator.cpp
new file mode 100644
index 0000000..cc9caa5
--- /dev/null
+++ b/displayengine/libs/core/fb/hw_rotator.cpp
@@ -0,0 +1,311 @@
+/*
+* Copyright (c) 2015, 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 <utils/debug.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include "hw_rotator.h"
+
+#define __CLASS__ "HWRotator"
+
+namespace sde {
+
+DisplayError HWRotatorInterface::Create(HWRotatorInterface **intf,
+ BufferSyncHandler *buffer_sync_handler) {
+ DisplayError error = kErrorNone;
+ HWRotator *hw_rotator = NULL;
+
+ hw_rotator = new HWRotator(buffer_sync_handler);
+ if (!hw_rotator) {
+ error = kErrorMemory;
+ } else {
+ *intf = hw_rotator;
+ }
+ return error;
+}
+
+DisplayError HWRotatorInterface::Destroy(HWRotatorInterface *intf) {
+ delete intf;
+ intf = NULL;
+
+ return kErrorNone;
+}
+
+HWRotator::HWRotator(BufferSyncHandler *buffer_sync_handler) : HWDevice(buffer_sync_handler) {
+ HWDevice::device_type_ = kDeviceRotator;
+ HWDevice::device_name_ = "Rotator Device";
+}
+
+DisplayError HWRotator::Open() {
+ DisplayError error = kErrorNone;
+
+ char device_name[64] = {0};
+ snprintf(device_name, sizeof(device_name), "%s", "/dev/mdss_rotator");
+
+ HWDevice::device_fd_ = open_(device_name, O_RDWR);
+ if (HWDevice::device_fd_ < 0) {
+ DLOGE("open %s failed err = %d errstr = %s", device_name, errno, strerror(errno));
+ return kErrorResources;
+ }
+
+ return error;
+}
+
+DisplayError HWRotator::Close() {
+ if (HWDevice::device_fd_ > 0) {
+ close_(HWDevice::device_fd_);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWRotator::OpenSession(HWRotateInfo *rotate_info) {
+ LayerBuffer *input_buffer = rotate_info->input_buffer;
+ HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+
+ ResetRotatorParams();
+
+ STRUCT_VAR(mdp_rotation_config, mdp_rot_config);
+ mdp_rot_config.version = MDP_ROTATION_REQUEST_VERSION_1_0;
+ mdp_rot_config.input.width = input_buffer->width;
+ mdp_rot_config.input.height = input_buffer->height;
+ HWDevice::SetFormat(input_buffer->format, &mdp_rot_config.input.format);
+ mdp_rot_config.output.width = rot_buf_info->output_buffer.width;
+ mdp_rot_config.output.height = rot_buf_info->output_buffer.height;
+ HWDevice::SetFormat(rot_buf_info->output_buffer.format, &mdp_rot_config.output.format);
+ mdp_rot_config.frame_rate = rotate_info->frame_rate;
+
+ if (ioctl_(HWDevice::device_fd_, MDSS_ROTATION_OPEN, &mdp_rot_config) < 0) {
+ IOCTL_LOGE(MDSS_ROTATION_OPEN, HWDevice::device_type_);
+ return kErrorHardware;
+ }
+
+ rot_buf_info->session_id = mdp_rot_config.session_id;
+
+ DLOGV_IF(kTagDriverConfig, "session_id %d", rot_buf_info->session_id);
+
+ return kErrorNone;
+}
+
+DisplayError HWRotator::CloseSession(int32_t session_id) {
+ if (ioctl_(HWDevice::device_fd_, MDSS_ROTATION_CLOSE, (uint32_t)session_id) < 0) {
+ IOCTL_LOGE(MDSS_ROTATION_CLOSE, HWDevice::device_type_);
+ return kErrorHardware;
+ }
+
+ DLOGV_IF(kTagDriverConfig, "session_id %d", session_id);
+
+ return kErrorNone;
+}
+
+void HWRotator::SetRotatorCtrlParams(HWLayers *hw_layers) {
+ DLOGV_IF(kTagDriverConfig, "************************* %s Validate Input ************************",
+ HWDevice::device_name_);
+
+ ResetRotatorParams();
+
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+
+ uint32_t &rot_count = mdp_rot_request_.count;
+ for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+ Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+ if (rotate_info->valid) {
+ HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+ mdp_rotation_item *mdp_rot_item = &mdp_rot_request_.list[rot_count];
+ bool rot90 = (layer.transform.rotation == 90.0f);
+
+ if (rot90) {
+ mdp_rot_item->flags |= MDP_ROTATION_90;
+ }
+
+ if (layer.transform.flip_horizontal) {
+ mdp_rot_item->flags |= MDP_ROTATION_FLIP_LR;
+ }
+
+ if (layer.transform.flip_vertical) {
+ mdp_rot_item->flags |= MDP_ROTATION_FLIP_UD;
+ }
+
+ HWDevice::SetRect(rotate_info->src_roi, &mdp_rot_item->src_rect);
+ HWDevice::SetRect(rotate_info->dst_roi, &mdp_rot_item->dst_rect);
+
+ // TODO(user): Need to assign the writeback id and pipe id returned from resource manager.
+ mdp_rot_item->pipe_idx = 0;
+ mdp_rot_item->wb_idx = 0;
+
+ mdp_rot_item->input.width = layer.input_buffer->width;
+ mdp_rot_item->input.height = layer.input_buffer->height;
+ HWDevice::SetFormat(layer.input_buffer->format, &mdp_rot_item->input.format);
+
+ mdp_rot_item->output.width = rot_buf_info->output_buffer.width;
+ mdp_rot_item->output.height = rot_buf_info->output_buffer.height;
+ HWDevice::SetFormat(rot_buf_info->output_buffer.format, &mdp_rot_item->output.format);
+
+ rot_count++;
+
+ DLOGV_IF(kTagDriverConfig, "******************** Layer[%d] %s rotate ********************",
+ i, count ? "Right" : "Left");
+ DLOGV_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d,\t out_w %d, out_h %d, out_f %d",
+ mdp_rot_item->input.width, mdp_rot_item->input.height, mdp_rot_item->input.format,
+ mdp_rot_item->output.width, mdp_rot_item->output.height,
+ mdp_rot_item->output.format);
+ DLOGV_IF(kTagDriverConfig, "pipe_id %d, wb_id %d, rot_flag %d", mdp_rot_item->pipe_idx,
+ mdp_rot_item->wb_idx, mdp_rot_item->flags);
+ DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_rot_item->src_rect.x,
+ mdp_rot_item->src_rect.y, mdp_rot_item->src_rect.w, mdp_rot_item->src_rect.h);
+ DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_rot_item->dst_rect.x,
+ mdp_rot_item->dst_rect.y, mdp_rot_item->dst_rect.w, mdp_rot_item->dst_rect.h);
+ DLOGV_IF(kTagDriverConfig, "*************************************************************");
+ }
+ }
+ }
+}
+
+void HWRotator::SetRotatorBufferParams(HWLayers *hw_layers) {
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ uint32_t rot_count = 0;
+
+ DLOGV_IF(kTagDriverConfig, "************************* %s Commit Input **************************",
+ HWDevice::device_name_);
+ DLOGV_IF(kTagDriverConfig, "Rotate layer count is %d", mdp_rot_request_.count);
+
+ for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+ Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+ if (rotate_info->valid) {
+ HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+ mdp_rotation_item *mdp_rot_item = &mdp_rot_request_.list[rot_count];
+
+ mdp_rot_item->input.planes[0].fd = layer.input_buffer->planes[0].fd;
+ mdp_rot_item->input.planes[0].offset = layer.input_buffer->planes[0].offset;
+ HWDevice::SetStride(HWDevice::device_type_, layer.input_buffer->format,
+ layer.input_buffer->width, &mdp_rot_item->input.planes[0].stride);
+ mdp_rot_item->input.plane_count = 1;
+ mdp_rot_item->input.fence = layer.input_buffer->acquire_fence_fd;
+
+ mdp_rot_item->output.planes[0].fd = rot_buf_info->output_buffer.planes[0].fd;
+ mdp_rot_item->output.planes[0].offset = rot_buf_info->output_buffer.planes[0].offset;
+ HWDevice::SetStride(HWDevice::device_type_, rot_buf_info->output_buffer.format,
+ rot_buf_info->output_buffer.planes[0].stride,
+ &mdp_rot_item->output.planes[0].stride);
+ mdp_rot_item->output.plane_count = 1;
+ mdp_rot_item->output.fence = -1;
+
+ rot_count++;
+
+ DLOGV_IF(kTagDriverConfig, "******************** Layer[%d] %s rotate ********************",
+ i, count ? "Right" : "Left");
+ DLOGV_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_stride %d, " \
+ "in_plane_count %d, in_fence %d", mdp_rot_item->input.planes[0].fd,
+ mdp_rot_item->input.planes[0].offset, mdp_rot_item->input.planes[0].stride,
+ mdp_rot_item->input.plane_count, mdp_rot_item->input.fence);
+ DLOGV_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, out_plane_count %d, " \
+ "out_fence %d", mdp_rot_item->output.planes[0].fd,
+ mdp_rot_item->output.planes[0].offset, mdp_rot_item->output.planes[0].stride,
+ mdp_rot_item->output.plane_count, mdp_rot_item->output.fence);
+ DLOGV_IF(kTagDriverConfig, "*************************************************************");
+ }
+ }
+ }
+}
+
+DisplayError HWRotator::Validate(HWLayers *hw_layers) {
+ SetRotatorCtrlParams(hw_layers);
+
+ mdp_rot_request_.flags = MDSS_ROTATION_REQUEST_VALIDATE;
+ if (ioctl_(HWDevice::device_fd_, MDSS_ROTATION_REQUEST, &mdp_rot_request_) < 0) {
+ IOCTL_LOGE(MDSS_ROTATION_REQUEST, HWDevice::device_type_);
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWRotator::Commit(HWLayers *hw_layers) {
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ uint32_t rot_count = 0;
+
+ SetRotatorCtrlParams(hw_layers);
+
+ SetRotatorBufferParams(hw_layers);
+
+ mdp_rot_request_.flags &= ~MDSS_ROTATION_REQUEST_VALIDATE;
+ if (ioctl_(HWDevice::device_fd_, MDSS_ROTATION_REQUEST, &mdp_rot_request_) < 0) {
+ IOCTL_LOGE(MDSS_ROTATION_REQUEST, HWDevice::device_type_);
+ return kErrorHardware;
+ }
+
+ for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+ Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+
+ layer.input_buffer->release_fence_fd = -1;
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+ if (rotate_info->valid) {
+ HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+ mdp_rotation_item *mdp_rot_item = &mdp_rot_request_.list[rot_count];
+
+ HWDevice::SyncMerge(layer.input_buffer->release_fence_fd, dup(mdp_rot_item->output.fence),
+ &layer.input_buffer->release_fence_fd);
+
+ rot_buf_info->output_buffer.acquire_fence_fd = dup(mdp_rot_item->output.fence);
+
+ close_(mdp_rot_item->output.fence);
+ rot_count++;
+ }
+ }
+ }
+
+ return kErrorNone;
+}
+
+void HWRotator::ResetRotatorParams() {
+ memset(&mdp_rot_request_, 0, sizeof(mdp_rot_request_));
+ memset(&mdp_rot_layers_, 0, sizeof(mdp_rot_layers_));
+
+ for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
+ mdp_rot_layers_[i].input.fence = -1;
+ mdp_rot_layers_[i].output.fence = -1;
+ }
+
+ mdp_rot_request_.version = MDP_ROTATION_REQUEST_VERSION_1_0;
+ mdp_rot_request_.list = mdp_rot_layers_;
+}
+
+} // namespace sde
+
diff --git a/displayengine/libs/core/fb/hw_rotator.h b/displayengine/libs/core/fb/hw_rotator.h
new file mode 100644
index 0000000..6e7727d
--- /dev/null
+++ b/displayengine/libs/core/fb/hw_rotator.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2015, 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 __HW_ROTATOR_H__
+#define __HW_ROTATOR_H__
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/msm_mdp_ext.h>
+#include <video/msm_hdmi_modes.h>
+#include <linux/mdss_rotator.h>
+#include <poll.h>
+#include <pthread.h>
+
+#include "hw_device.h"
+#include "hw_rotator_interface.h"
+
+namespace sde {
+
+class HWRotator : public HWDevice, public HWRotatorInterface {
+ public:
+ explicit HWRotator(BufferSyncHandler *buffer_sync_handler);
+ virtual DisplayError Open();
+ virtual DisplayError Close();
+ virtual DisplayError OpenSession(HWRotateInfo *hw_layers);
+ virtual DisplayError CloseSession(int32_t session_id);
+ virtual DisplayError Validate(HWLayers *hw_layers);
+ virtual DisplayError Commit(HWLayers *hw_layers);
+
+ private:
+ void ResetRotatorParams();
+ void SetRotatorCtrlParams(HWLayers *hw_layers);
+ void SetRotatorBufferParams(HWLayers *hw_layers);
+
+ struct mdp_rotation_request mdp_rot_request_;
+ struct mdp_rotation_item mdp_rot_layers_[kMaxSDELayers * 2]; // split panel (left + right)
+};
+
+} // namespace sde
+
+#endif // __HW_ROTATOR_H__
+
diff --git a/displayengine/libs/core/fb/hw_virtual.cpp b/displayengine/libs/core/fb/hw_virtual.cpp
new file mode 100644
index 0000000..2d7cd3e
--- /dev/null
+++ b/displayengine/libs/core/fb/hw_virtual.cpp
@@ -0,0 +1,134 @@
+/*
+* Copyright (c) 2015, 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 <utils/debug.h>
+#include "hw_virtual.h"
+
+#define __CLASS__ "HWVirtual"
+
+namespace sde {
+
+DisplayError HWVirtualInterface::Create(HWVirtualInterface **intf, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler) {
+ DisplayError error = kErrorNone;
+ HWVirtual *hw_virtual = NULL;
+
+ hw_virtual = new HWVirtual(buffer_sync_handler, hw_info_intf);
+ error = hw_virtual->Init();
+ if (UNLIKELY(error != kErrorNone)) {
+ delete hw_virtual;
+ } else {
+ *intf = hw_virtual;
+ }
+
+ return error;
+}
+
+DisplayError HWVirtualInterface::Destroy(HWVirtualInterface *intf) {
+ HWVirtual *hw_virtual = static_cast<HWVirtual *>(intf);
+ hw_virtual->Deinit();
+ delete hw_virtual;
+
+ return kErrorNone;
+}
+
+HWVirtual::HWVirtual(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
+ : HWDevice(buffer_sync_handler) {
+ HWDevice::device_type_ = kDeviceVirtual;
+ HWDevice::device_name_ = "Virtual Display Device";
+ HWDevice::hw_info_intf_ = hw_info_intf;
+}
+
+DisplayError HWVirtual::Init() {
+ return HWDevice::Init();
+}
+
+DisplayError HWVirtual::Deinit() {
+ return kErrorNone;
+}
+
+DisplayError HWVirtual::Open(HWEventHandler *eventhandler) {
+ return HWDevice::Open(eventhandler);
+}
+
+DisplayError HWVirtual::Close() {
+ return HWDevice::Close();
+}
+
+DisplayError HWVirtual::GetNumDisplayAttributes(uint32_t *count) {
+ return HWDevice::GetNumDisplayAttributes(count);
+}
+
+DisplayError HWVirtual::GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+ uint32_t index) {
+ return HWDevice::GetDisplayAttributes(display_attributes, index);
+}
+
+DisplayError HWVirtual::SetDisplayAttributes(uint32_t index) {
+ return HWDevice::SetDisplayAttributes(index);
+}
+
+DisplayError HWVirtual::GetConfigIndex(uint32_t mode, uint32_t *index) {
+ return HWDevice::GetConfigIndex(mode, index);
+}
+
+DisplayError HWVirtual::PowerOn() {
+ return HWDevice::PowerOn();
+}
+
+DisplayError HWVirtual::PowerOff() {
+ return HWDevice::PowerOff();
+}
+
+DisplayError HWVirtual::Doze() {
+ return HWDevice::Doze();
+}
+
+DisplayError HWVirtual::Standby() {
+ return HWDevice::Standby();
+}
+
+DisplayError HWVirtual::Validate(HWLayers *hw_layers) {
+ return HWDevice::Validate(hw_layers);
+}
+
+DisplayError HWVirtual::Commit(HWLayers *hw_layers) {
+ return HWDevice::Commit(hw_layers);
+}
+
+DisplayError HWVirtual::Flush() {
+ return HWDevice::Flush();
+}
+
+DisplayError HWVirtual::GetHWPanelInfo(HWPanelInfo *panel_info) {
+ return HWDevice::GetHWPanelInfo(panel_info);
+}
+
+} // namespace sde
+
diff --git a/displayengine/libs/core/fb/hw_virtual.h b/displayengine/libs/core/fb/hw_virtual.h
new file mode 100644
index 0000000..fb7c784
--- /dev/null
+++ b/displayengine/libs/core/fb/hw_virtual.h
@@ -0,0 +1,58 @@
+/*
+* Copyright (c) 2015, 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 __HW_VIRTUAL_H__
+#define __HW_VIRTUAL_H__
+
+#include "hw_device.h"
+#include "hw_virtual_interface.h"
+
+namespace sde {
+
+class HWVirtual : public HWDevice, public HWVirtualInterface {
+ public:
+ HWVirtual(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
+ virtual DisplayError Init();
+ virtual DisplayError Deinit();
+ virtual DisplayError Open(HWEventHandler *eventhandler);
+ virtual DisplayError Close();
+ virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+ virtual DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+ uint32_t index);
+ virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
+ virtual DisplayError SetDisplayAttributes(uint32_t index);
+ virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+ virtual DisplayError PowerOn();
+ virtual DisplayError PowerOff();
+ virtual DisplayError Doze();
+ virtual DisplayError Standby();
+ virtual DisplayError Validate(HWLayers *hw_layers);
+ virtual DisplayError Commit(HWLayers *hw_layers);
+ virtual DisplayError Flush();
+};
+
+} // namespace sde
+
+#endif // __HW_VIRTUAL_H__
+
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
deleted file mode 100644
index f3cdb8b..0000000
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ /dev/null
@@ -1,1683 +0,0 @@
-/*
-* Copyright (c) 2014 - 2015, 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.
-*/
-
-#define __STDC_FORMAT_MACROS
-#include <ctype.h>
-#include <math.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <linux/fb.h>
-#include <sys/resource.h>
-#include <sys/prctl.h>
-#include <pthread.h>
-#include <utils/constants.h>
-#include <utils/debug.h>
-
-#include "hw_framebuffer.h"
-#include "scalar_helper.h"
-
-#define __CLASS__ "HWFrameBuffer"
-
-#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, \
- type, errno, strerror(errno))
-
-#ifdef DISPLAY_CORE_VIRTUAL_DRIVER
-extern int virtual_ioctl(int fd, int cmd, ...);
-extern int virtual_open(const char *file_name, int access, ...);
-extern int virtual_close(int fd);
-extern int virtual_poll(struct pollfd *fds, nfds_t num, int timeout);
-extern ssize_t virtual_pread(int fd, void *data, size_t count, off_t offset);
-extern ssize_t virtual_pwrite(int fd, const void *data, size_t count, off_t offset);
-extern FILE* virtual_fopen(const char *fname, const char *mode);
-extern int virtual_fclose(FILE* fileptr);
-extern ssize_t virtual_getline(char **lineptr, size_t *linelen, FILE *stream);
-
-#endif
-
-namespace sde {
-
-HWFrameBuffer::HWFrameBuffer(BufferSyncHandler *buffer_sync_handler)
- : event_thread_name_("SDE_EventThread"), fake_vsync_(false), exit_threads_(false),
- fb_path_("/sys/devices/virtual/graphics/fb"), hotplug_enabled_(false),
- buffer_sync_handler_(buffer_sync_handler) {
- // Pointer to actual driver interfaces.
- ioctl_ = ::ioctl;
- open_ = ::open;
- close_ = ::close;
- poll_ = ::poll;
- pread_ = ::pread;
- pwrite_ = ::pwrite;
- fopen_ = ::fopen;
- fclose_ = ::fclose;
- getline_ = ::getline;
-
-#ifdef DISPLAY_CORE_VIRTUAL_DRIVER
- // If debug property to use virtual driver is set, point to virtual driver interfaces.
- if (Debug::IsVirtualDriver()) {
- ioctl_ = virtual_ioctl;
- open_ = virtual_open;
- close_ = virtual_close;
- poll_ = virtual_poll;
- pread_ = virtual_pread;
- pwrite_ = virtual_pwrite;
- fopen_ = virtual_fopen;
- fclose_ = virtual_fclose;
- getline_ = virtual_getline;
- }
-#endif
- for (int i = 0; i < kDeviceMax; i++) {
- fb_node_index_[i] = -1;
- }
-}
-
-DisplayError HWFrameBuffer::Init() {
- DisplayError error = kErrorNone;
- char node_path[kMaxStringLength] = {0};
- char data[kMaxStringLength] = {0};
- const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify"};
-
- // Read the fb node index
- PopulateFBNodeIndex();
- if (fb_node_index_[kHWPrimary] == -1) {
- DLOGE("HW Display Device Primary should be present");
- error = kErrorHardware;
- goto CleanupOnError;
- }
-
- // Populate Primary Panel Info(Used for Partial Update)
- PopulatePanelInfo(fb_node_index_[kHWPrimary]);
- // Populate HW Capabilities
- error = PopulateHWCapabilities();
- if (error != kErrorNone) {
- goto CleanupOnError;
- }
-
- // Open nodes for polling
- for (int display = 0; display < kNumPhysicalDisplays; display++) {
- for (int event = 0; event < kNumDisplayEvents; event++) {
- poll_fds_[display][event].fd = -1;
- }
- }
-
- if (!fake_vsync_) {
- for (int display = 0; display < kNumPhysicalDisplays; display++) {
- for (int event = 0; event < kNumDisplayEvents; event++) {
- pollfd &poll_fd = poll_fds_[display][event];
-
- if ((primary_panel_info_.type == kCommandModePanel) && (display == kDevicePrimary) &&
- (!strncmp(event_name[event], "idle_notify", strlen("idle_notify")))) {
- continue;
- }
-
- snprintf(node_path, sizeof(node_path), "%s%d/%s", fb_path_, fb_node_index_[display],
- event_name[event]);
-
- poll_fd.fd = open_(node_path, O_RDONLY);
- if (poll_fd.fd < 0) {
- DLOGE("open failed for display=%d event=%d, error=%s", display, event, strerror(errno));
- error = kErrorHardware;
- goto CleanupOnError;
- }
-
- // Read once on all fds to clear data on all fds.
- pread_(poll_fd.fd, data , kMaxStringLength, 0);
- poll_fd.events = POLLPRI | POLLERR;
- }
- }
- }
-
- // Mode look-up table for HDMI
- supported_video_modes_ = new msm_hdmi_mode_timing_info[HDMI_VFRMT_MAX];
- if (!supported_video_modes_) {
- error = kErrorMemory;
- goto CleanupOnError;
- }
- // Populate the mode table for supported modes
- MSM_HDMI_MODES_INIT_TIMINGS(supported_video_modes_);
- MSM_HDMI_MODES_SET_SUPP_TIMINGS(supported_video_modes_, MSM_HDMI_MODES_ALL);
-
- // Start the Event thread
- if (pthread_create(&event_thread_, NULL, &DisplayEventThread, this) < 0) {
- DLOGE("Failed to start %s, error = %s", event_thread_name_);
- error = kErrorResources;
- goto CleanupOnError;
- }
-
- // Disable HPD at start if HDMI is external, it will be enabled later when the display powers on
- // This helps for framework reboot or adb shell stop/start
- EnableHotPlugDetection(0);
-
- return kErrorNone;
-
-CleanupOnError:
- // Close all poll fds
- for (int display = 0; display < kNumPhysicalDisplays; display++) {
- for (int event = 0; event < kNumDisplayEvents; event++) {
- int &fd = poll_fds_[display][event].fd;
- if (fd >= 0) {
- close_(fd);
- }
- }
- }
- if (supported_video_modes_) {
- delete supported_video_modes_;
- }
-
- return error;
-}
-
-DisplayError HWFrameBuffer::Deinit() {
- exit_threads_ = true;
- pthread_join(event_thread_, NULL);
-
- for (int display = 0; display < kNumPhysicalDisplays; display++) {
- for (int event = 0; event < kNumDisplayEvents; event++) {
- close_(poll_fds_[display][event].fd);
- }
- }
- if (supported_video_modes_) {
- delete supported_video_modes_;
- }
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::GetHWCapabilities(HWResourceInfo *hw_res_info) {
- *hw_res_info = hw_resource_;
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::Open(HWDeviceType type, Handle *device, HWEventHandler* eventhandler) {
- DisplayError error = kErrorNone;
-
- HWContext *hw_context = new HWContext();
- if (!hw_context) {
- return kErrorMemory;
- }
-
- char device_name[64] = {0};
-
- switch (type) {
- case kDevicePrimary:
- case kDeviceHDMI:
- // Store EventHandlers for two Physical displays, i.e., Primary and HDMI
- // TODO(user): Need to revisit for HDMI as Primary usecase
- event_handler_[type] = eventhandler;
- case kDeviceVirtual:
- snprintf(device_name, sizeof(device_name), "%s%d", "/dev/graphics/fb", fb_node_index_[type]);
- break;
- case kDeviceRotator:
- snprintf(device_name, sizeof(device_name), "%s", "/dev/mdss_rotator");
- break;
- default:
- break;
- }
-
- hw_context->device_fd = open_(device_name, O_RDWR);
- if (hw_context->device_fd < 0) {
- DLOGE("open %s failed err = %d errstr = %s", device_name, errno, strerror(errno));
- delete hw_context;
- return kErrorResources;
- }
-
- hw_context->type = type;
-
- *device = hw_context;
-
- return error;
-}
-
-DisplayError HWFrameBuffer::Close(Handle device) {
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
-
- switch (hw_context->type) {
- case kDevicePrimary:
- case kDeviceVirtual:
- break;
- case kDeviceHDMI:
- hdmi_mode_count_ = 0;
- break;
- default:
- break;
- }
-
- if (hw_context->device_fd > 0) {
- close_(hw_context->device_fd);
- }
- delete hw_context;
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::GetNumDisplayAttributes(Handle device, uint32_t *count) {
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
-
- switch (hw_context->type) {
- case kDevicePrimary:
- case kDeviceVirtual:
- *count = 1;
- break;
- case kDeviceHDMI:
- *count = GetHDMIModeCount();
- if (*count <= 0) {
- return kErrorHardware;
- }
- break;
- default:
- return kErrorParameters;
- }
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::GetDisplayAttributes(Handle device,
- HWDisplayAttributes *display_attributes,
- uint32_t index) {
- DTRACE_SCOPED();
-
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
- int &device_fd = hw_context->device_fd;
- // Variable screen info
- STRUCT_VAR(fb_var_screeninfo, var_screeninfo);
-
- switch (hw_context->type) {
- case kDevicePrimary:
- {
- if (ioctl_(device_fd, FBIOGET_VSCREENINFO, &var_screeninfo) < 0) {
- IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
- return kErrorHardware;
- }
-
- // Frame rate
- STRUCT_VAR(msmfb_metadata, meta_data);
- meta_data.op = metadata_op_frame_rate;
- if (ioctl_(device_fd, MSMFB_METADATA_GET, &meta_data) < 0) {
- IOCTL_LOGE(MSMFB_METADATA_GET, hw_context->type);
- return kErrorHardware;
- }
-
- // If driver doesn't return width/height information, default to 160 dpi
- if (INT(var_screeninfo.width) <= 0 || INT(var_screeninfo.height) <= 0) {
- var_screeninfo.width = INT(((FLOAT(var_screeninfo.xres) * 25.4f)/160.0f) + 0.5f);
- var_screeninfo.height = INT(((FLOAT(var_screeninfo.yres) * 25.4f)/160.0f) + 0.5f);
- }
-
- display_attributes->x_pixels = var_screeninfo.xres;
- display_attributes->y_pixels = var_screeninfo.yres;
- display_attributes->v_total = var_screeninfo.yres + var_screeninfo.lower_margin +
- var_screeninfo.upper_margin + var_screeninfo.vsync_len;
- display_attributes->x_dpi =
- (FLOAT(var_screeninfo.xres) * 25.4f) / FLOAT(var_screeninfo.width);
- display_attributes->y_dpi =
- (FLOAT(var_screeninfo.yres) * 25.4f) / FLOAT(var_screeninfo.height);
- display_attributes->fps = FLOAT(meta_data.data.panel_frame_rate);
- display_attributes->vsync_period_ns = UINT32(1000000000L / display_attributes->fps);
- display_attributes->is_device_split = (hw_resource_.split_info.left_split ||
- (var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false;
- display_attributes->split_left = hw_resource_.split_info.left_split ?
- hw_resource_.split_info.left_split : display_attributes->x_pixels / 2;
- }
- break;
-
- case kDeviceHDMI:
- {
- // Get the resolution info from the look up table
- msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[0];
- for (int i = 0; i < HDMI_VFRMT_MAX; i++) {
- msm_hdmi_mode_timing_info *cur = &supported_video_modes_[i];
- if (cur->video_format == hdmi_modes_[index]) {
- timing_mode = cur;
- break;
- }
- }
- display_attributes->x_pixels = timing_mode->active_h;
- display_attributes->y_pixels = timing_mode->active_v;
- display_attributes->v_total = timing_mode->active_v + timing_mode->front_porch_v +
- 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) / 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) {
- display_attributes->is_device_split = true;
- display_attributes->split_left = display_attributes->x_pixels / 2;
- }
- }
- break;
-
- case kDeviceVirtual:
- break;
-
- default:
- return kErrorParameters;
- }
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::SetDisplayAttributes(Handle device, uint32_t index) {
- DTRACE_SCOPED();
-
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
- DisplayError error = kErrorNone;
-
- switch (hw_context->type) {
- case kDevicePrimary:
- case kDeviceVirtual:
- break;
-
- case kDeviceHDMI:
- {
- // Variable screen info
- STRUCT_VAR(fb_var_screeninfo, vscreeninfo);
- if (ioctl_(hw_context->device_fd, FBIOGET_VSCREENINFO, &vscreeninfo) < 0) {
- IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
- return kErrorHardware;
- }
-
- DLOGI("GetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3],
- vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
- vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
- vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
-
- msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[0];
- for (int i = 0; i < HDMI_VFRMT_MAX; i++) {
- msm_hdmi_mode_timing_info *cur = &supported_video_modes_[i];
- if (cur->video_format == hdmi_modes_[index]) {
- timing_mode = cur;
- break;
- }
- }
-
- if (MapHDMIDisplayTiming(timing_mode, &vscreeninfo) == false) {
- return kErrorParameters;
- }
-
- STRUCT_VAR(msmfb_metadata, metadata);
- metadata.op = metadata_op_vic;
- metadata.data.video_info_code = timing_mode->video_format;
- if (ioctl(hw_context->device_fd, MSMFB_METADATA_SET, &metadata) < 0) {
- IOCTL_LOGE(MSMFB_METADATA_SET, hw_context->type);
- return kErrorHardware;
- }
-
- DLOGI("SetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3] & 0xFF00,
- vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
- vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
- vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
-
- vscreeninfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
- if (ioctl_(hw_context->device_fd, FBIOPUT_VSCREENINFO, &vscreeninfo) < 0) {
- IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
- return kErrorHardware;
- }
- }
- break;
-
- default:
- return kErrorParameters;
- }
-
- return error;
-}
-
-DisplayError HWFrameBuffer::GetConfigIndex(Handle device, uint32_t mode, uint32_t *index) {
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
-
- switch (hw_context->type) {
- case kDevicePrimary:
- case kDeviceVirtual:
- return kErrorNone;
- break;
- case kDeviceHDMI:
- // Check if the mode is valid and return corresponding index
- for (uint32_t i = 0; i < hdmi_mode_count_; i++) {
- if (hdmi_modes_[i] == mode) {
- *index = i;
- DLOGI("Index = %d for config = %d", *index, mode);
- return kErrorNone;
- }
- }
- break;
- default:
- return kErrorParameters;
- }
-
- DLOGE("Config = %d not supported", mode);
- return kErrorNotSupported;
-}
-
-
-DisplayError HWFrameBuffer::PowerOn(Handle device) {
- DTRACE_SCOPED();
-
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
-
- if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
- IOCTL_LOGE(FB_BLANK_UNBLANK, hw_context->type);
- return kErrorHardware;
- }
-
- // Need to turn on HPD
- if (!hotplug_enabled_) {
- hotplug_enabled_ = EnableHotPlugDetection(1);
- }
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::PowerOff(Handle device) {
- DTRACE_SCOPED();
-
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
- HWDisplay *hw_display = &hw_context->hw_display;
-
- switch (hw_context->type) {
- case kDevicePrimary:
- if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
- IOCTL_LOGE(FB_BLANK_POWERDOWN, hw_context->type);
- return kErrorHardware;
- }
- break;
- default:
- break;
- }
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::Doze(Handle device) {
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::Standby(Handle device) {
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::SetVSyncState(Handle device, bool enable) {
- DTRACE_SCOPED();
-
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
- int vsync_on = enable ? 1 : 0;
- if (ioctl_(hw_context->device_fd, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) < 0) {
- IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, hw_context->type);
- return kErrorHardware;
- }
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::OpenRotatorSession(Handle device, HWRotateInfo *rotate_info) {
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
- HWRotator *hw_rotator = &hw_context->hw_rotator;
- LayerBuffer *input_buffer = rotate_info->input_buffer;
- HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
-
- hw_rotator->Reset();
-
- STRUCT_VAR(mdp_rotation_config, mdp_rot_config);
- mdp_rot_config.version = MDP_ROTATION_REQUEST_VERSION_1_0;
- mdp_rot_config.input.width = input_buffer->width;
- mdp_rot_config.input.height = input_buffer->height;
- SetFormat(input_buffer->format, &mdp_rot_config.input.format);
- mdp_rot_config.output.width = rot_buf_info->output_buffer.width;
- mdp_rot_config.output.height = rot_buf_info->output_buffer.height;
- SetFormat(rot_buf_info->output_buffer.format, &mdp_rot_config.output.format);
- mdp_rot_config.frame_rate = rotate_info->frame_rate;
-
- if (ioctl_(hw_context->device_fd, MDSS_ROTATION_OPEN, &mdp_rot_config) < 0) {
- IOCTL_LOGE(MDSS_ROTATION_OPEN, hw_context->type);
- return kErrorHardware;
- }
-
- rot_buf_info->session_id = mdp_rot_config.session_id;
-
- DLOGV_IF(kTagDriverConfig, "session_id %d", rot_buf_info->session_id);
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::CloseRotatorSession(Handle device, int32_t session_id) {
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
-
- if (ioctl_(hw_context->device_fd, MDSS_ROTATION_CLOSE, (uint32_t)session_id) < 0) {
- IOCTL_LOGE(MDSS_ROTATION_CLOSE, hw_context->type);
- return kErrorHardware;
- }
-
- DLOGV_IF(kTagDriverConfig, "session_id %d", session_id);
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::Validate(Handle device, HWLayers *hw_layers) {
- DTRACE_SCOPED();
-
- DisplayError error = kErrorNone;
-
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
- switch (hw_context->type) {
- case kDevicePrimary:
- case kDeviceHDMI:
- case kDeviceVirtual:
- error = DisplayValidate(hw_context, hw_layers);
- if (error != kErrorNone) {
- return error;
- }
- break;
- case kDeviceRotator:
- error = RotatorValidate(hw_context, hw_layers);
- if (error != kErrorNone) {
- return error;
- }
- break;
- default:
- break;
- }
- return error;
-}
-
-DisplayError HWFrameBuffer::Commit(Handle device, HWLayers *hw_layers) {
- DisplayError error = kErrorNone;
-
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
- switch (hw_context->type) {
- case kDevicePrimary:
- case kDeviceHDMI:
- case kDeviceVirtual:
- error = DisplayCommit(hw_context, hw_layers);
- if (error != kErrorNone) {
- return error;
- }
- break;
- case kDeviceRotator:
- error = RotatorCommit(hw_context, hw_layers);
- if (error != kErrorNone) {
- return error;
- }
- break;
- default:
- break;
- }
- return error;
-}
-
-DisplayError HWFrameBuffer::DisplayValidate(HWContext *hw_context, HWLayers *hw_layers) {
- DisplayError error = kErrorNone;
- HWDisplay *hw_display = &hw_context->hw_display;
-
- hw_display->Reset();
-
- HWLayersInfo &hw_layer_info = hw_layers->info;
- LayerStack *stack = hw_layer_info.stack;
-
- DLOGV_IF(kTagDriverConfig, "************************** %s Validate Input ***********************",
- GetDeviceString(hw_context->type));
- DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
-
- mdp_layer_commit_v1 &mdp_commit = hw_display->mdp_disp_commit.commit_v1;
- mdp_input_layer *mdp_layers = hw_display->mdp_in_layers;
- mdp_output_layer *mdp_out_layer = &hw_display->mdp_out_layer;
- uint32_t &mdp_layer_count = mdp_commit.input_layer_cnt;
-
- for (uint32_t i = 0; i < hw_layer_info.count; i++) {
- uint32_t layer_index = hw_layer_info.index[i];
- Layer &layer = stack->layers[layer_index];
- LayerBuffer *input_buffer = layer.input_buffer;
- HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
- HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
- mdp_input_layer mdp_layer;
-
- for (uint32_t count = 0; count < 2; count++) {
- HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
- HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
-
- if (rotate_info->valid) {
- input_buffer = &rotate_info->hw_buffer_info.output_buffer;
- }
-
- if (pipe_info->valid) {
- mdp_input_layer &mdp_layer = mdp_layers[mdp_layer_count];
- mdp_layer_buffer &mdp_buffer = mdp_layer.buffer;
-
- mdp_buffer.width = input_buffer->width;
- mdp_buffer.height = input_buffer->height;
-
- error = SetFormat(input_buffer->format, &mdp_buffer.format);
- if (error != kErrorNone) {
- return error;
- }
-
- mdp_layer.alpha = layer.plane_alpha;
- mdp_layer.z_order = UINT16(pipe_info->z_order);
- mdp_layer.transp_mask = 0xffffffff;
- SetBlending(layer.blending, &mdp_layer.blend_op);
- mdp_layer.pipe_ndx = pipe_info->pipe_id;
- mdp_layer.horz_deci = pipe_info->horizontal_decimation;
- mdp_layer.vert_deci = pipe_info->vertical_decimation;
-
- SetRect(pipe_info->src_roi, &mdp_layer.src_rect);
- SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect);
-
- // Flips will be taken care by rotator, if layer requires 90 rotation. So Dont use MDP for
- // flip operation, if layer transform is 90.
- if (!layer.transform.rotation) {
- 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_scale_data* mdp_scale = hw_display->GetScaleDataRef(mdp_layer_count);
-#ifdef USES_SCALAR
- // Set the configured scale data for MDP driver
- ScalarHelper::GetInstance()->SetScaleData(i, !count, mdp_scale);
- if (mdp_scale->enable_pxl_ext) {
- if ((mdp_layer.flags & MDP_LAYER_DEINTERLACE) && (layer.transform.rotation == 90.0f))
- ScalarHelper::GetInstance()->UpdateSrcWidth(i, !count, &mdp_buffer.width);
- }
-#endif
- mdp_layer.scale = mdp_scale;
- mdp_layer_count++;
-
- DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
- i, count ? "Right" : "Left");
- DLOGV_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d", mdp_buffer.width, mdp_buffer.height,
- mdp_buffer.format);
- DLOGV_IF(kTagDriverConfig, "plane_alpha %d, zorder %d, blending %d, horz_deci %d, "
- "vert_deci %d", mdp_layer.alpha, mdp_layer.z_order, mdp_layer.blend_op,
- mdp_layer.horz_deci, mdp_layer.vert_deci);
- DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_layer.src_rect.x,
- mdp_layer.src_rect.y, mdp_layer.src_rect.w, mdp_layer.src_rect.h);
- DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_layer.dst_rect.x,
- mdp_layer.dst_rect.y, mdp_layer.dst_rect.w, mdp_layer.dst_rect.h);
- for (int j = 0; j < MAX_PLANES; j++) {
- DLOGV_IF(kTagDriverConfig, "Scale Data[%d]: Phase=[%x %x %x %x] Pixel_Ext=[%d %d %d %d]",
- j, mdp_layer.scale->init_phase_x[j], mdp_layer.scale->phase_step_x[j],
- mdp_layer.scale->init_phase_y[j], mdp_layer.scale->phase_step_y[j],
- mdp_layer.scale->num_ext_pxls_left[j], mdp_layer.scale->num_ext_pxls_top[j],
- mdp_layer.scale->num_ext_pxls_right[j], mdp_layer.scale->num_ext_pxls_btm[j]);
- DLOGV_IF(kTagDriverConfig, "Fetch=[%d %d %d %d] Repeat=[%d %d %d %d] roi_width = %d",
- mdp_layer.scale->left_ftch[j], mdp_layer.scale->top_ftch[j],
- mdp_layer.scale->right_ftch[j], mdp_layer.scale->btm_ftch[j],
- mdp_layer.scale->left_rpt[j], mdp_layer.scale->top_rpt[j],
- mdp_layer.scale->right_rpt[j], mdp_layer.scale->btm_rpt[j],
- mdp_layer.scale->roi_w[j]);
- }
- DLOGV_IF(kTagDriverConfig, "*************************************************************");
- }
- }
- }
-
- if (hw_context->type == kDeviceVirtual) {
- LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
- // TODO(user): Need to assign the writeback id from the resource manager, since the support
- // has not been added hard coding it to 2 for now.
- mdp_out_layer->writeback_ndx = 2;
- mdp_out_layer->buffer.width = output_buffer->width;
- mdp_out_layer->buffer.height = output_buffer->height;
- SetFormat(output_buffer->format, &mdp_out_layer->buffer.format);
-
- DLOGI_IF(kTagDriverConfig, "******************* Output buffer Info **********************");
- DLOGI_IF(kTagDriverConfig, "out_w %d, out_h %d, out_f %d, wb_id %d",
- mdp_out_layer->buffer.width, mdp_out_layer->buffer.height,
- mdp_out_layer->buffer.format, mdp_out_layer->writeback_ndx);
- DLOGI_IF(kTagDriverConfig, "*************************************************************");
- }
-
- mdp_commit.flags |= MDP_VALIDATE_LAYER;
- if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) < 0) {
- IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
- DumpLayerCommit(hw_display->mdp_disp_commit);
- return kErrorHardware;
- }
-
- return kErrorNone;
-}
-
-void HWFrameBuffer::DumpLayerCommit(mdp_layer_commit &layer_commit) {
- mdp_layer_commit_v1 &mdp_commit = layer_commit.commit_v1;
- mdp_input_layer *mdp_layers = mdp_commit.input_layers;
-
- DLOGE("mdp_commt: flags = %x, release fence = %x", mdp_commit.flags, mdp_commit.release_fence);
- DLOGE("left_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.left_roi.x, mdp_commit.left_roi.y,
- mdp_commit.left_roi.w, mdp_commit.left_roi.h);
- DLOGE("right_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.right_roi.x,
- mdp_commit.right_roi.y, mdp_commit.right_roi.w, mdp_commit.right_roi.h);
- for (uint32_t i = 0; i < mdp_commit.input_layer_cnt; i++) {
- DLOGE("mdp_commt: layer_cnt = %d, pipe_ndx = %x, zorder = %d, flags = %x",
- i, mdp_layers[i].pipe_ndx, mdp_layers[i].z_order, mdp_layers[i].flags);
- mdp_rect &src_rect = mdp_layers[i].src_rect;
- DLOGE("src rect: x = %d, y = %d, w = %d, h = %d",
- src_rect.x, src_rect.y, src_rect.w, src_rect.h);
- mdp_rect &dst_rect = mdp_layers[i].dst_rect;
- DLOGE("dst rect: x = %d, y = %d, w = %d, h = %d",
- dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h);
- }
-}
-
-DisplayError HWFrameBuffer::DisplayCommit(HWContext *hw_context, HWLayers *hw_layers) {
- DTRACE_SCOPED();
-
- HWDisplay *hw_display = &hw_context->hw_display;
- HWLayersInfo &hw_layer_info = hw_layers->info;
- LayerStack *stack = hw_layer_info.stack;
-
- DLOGV_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
- GetDeviceString(hw_context->type));
- DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
-
- mdp_layer_commit_v1 &mdp_commit = hw_display->mdp_disp_commit.commit_v1;
- mdp_input_layer *mdp_layers = hw_display->mdp_in_layers;
- mdp_output_layer *mdp_out_layer = &hw_display->mdp_out_layer;
- uint32_t mdp_layer_index = 0;
-
- for (uint32_t i = 0; i < hw_layer_info.count; i++) {
- uint32_t layer_index = hw_layer_info.index[i];
- LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
- HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
- HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
-
- for (uint32_t count = 0; count < 2; count++) {
- HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
- HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
-
- if (rotate_info->valid) {
- input_buffer = &rotate_info->hw_buffer_info.output_buffer;
- }
-
- if (pipe_info->valid) {
- mdp_layer_buffer &mdp_buffer = mdp_layers[mdp_layer_index].buffer;
- mdp_input_layer &mdp_layer = mdp_layers[mdp_layer_index];
- if (input_buffer->planes[0].fd >= 0) {
- mdp_buffer.plane_count = 1;
- mdp_buffer.planes[0].fd = input_buffer->planes[0].fd;
- mdp_buffer.planes[0].offset = input_buffer->planes[0].offset;
- SetStride(hw_context->type, input_buffer->format, input_buffer->planes[0].stride,
- &mdp_buffer.planes[0].stride);
- } else {
- DLOGW("Invalid buffer fd, setting plane count to 0");
- mdp_buffer.plane_count = 0;
- }
-
- mdp_buffer.fence = input_buffer->acquire_fence_fd;
- mdp_layer_index++;
-
- DLOGV_IF(kTagDriverConfig, "****************** Layer[%d] %s pipe Input *******************",
- i, count ? "Right" : "Left");
- DLOGI_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d, horz_deci %d, vert_deci %d",
- mdp_buffer.width, mdp_buffer.height, mdp_buffer.format, mdp_layer.horz_deci,
- mdp_layer.vert_deci);
- DLOGI_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_buf_stride %d, " \
- "in_plane_count %d, in_fence %d, layer count %d", mdp_buffer.planes[0].fd,
- mdp_buffer.planes[0].offset, mdp_buffer.planes[0].stride, mdp_buffer.plane_count,
- mdp_buffer.fence, mdp_commit.input_layer_cnt);
- DLOGV_IF(kTagDriverConfig, "*************************************************************");
- }
- }
- }
- if (hw_context->type == kDeviceVirtual) {
- LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
-
- if (output_buffer->planes[0].fd >= 0) {
- mdp_out_layer->buffer.planes[0].fd = output_buffer->planes[0].fd;
- mdp_out_layer->buffer.planes[0].offset = output_buffer->planes[0].offset;
- SetStride(hw_context->type, output_buffer->format, output_buffer->planes[0].stride,
- &mdp_out_layer->buffer.planes[0].stride);
- mdp_out_layer->buffer.plane_count = 1;
- } else {
- DLOGW("Invalid output buffer fd, setting plane count to 0");
- mdp_out_layer->buffer.plane_count = 0;
- }
-
- mdp_out_layer->buffer.fence = output_buffer->acquire_fence_fd;
-
- DLOGI_IF(kTagDriverConfig, "******************* Output buffer Info **********************");
- DLOGI_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, acquire_fence %d",
- mdp_out_layer->buffer.planes[0].fd, mdp_out_layer->buffer.planes[0].offset,
- mdp_out_layer->buffer.planes[0].stride, mdp_out_layer->buffer.fence);
- DLOGI_IF(kTagDriverConfig, "*************************************************************");
- }
-
- mdp_commit.release_fence = -1;
- mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
- if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) < 0) {
- IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
- DumpLayerCommit(hw_display->mdp_disp_commit);
- return kErrorHardware;
- }
-
- stack->retire_fence_fd = mdp_commit.retire_fence;
-
- // MDP returns only one release fence for the entire layer stack. Duplicate this fence into all
- // layers being composed by MDP.
- for (uint32_t i = 0; i < hw_layer_info.count; i++) {
- uint32_t layer_index = hw_layer_info.index[i];
- LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
- HWRotateInfo *left_rotate = &hw_layers->config[i].rotates[0];
- HWRotateInfo *right_rotate = &hw_layers->config[i].rotates[1];
-
- if (!left_rotate->valid && !right_rotate->valid) {
- input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
- continue;
- }
-
- for (uint32_t count = 0; count < 2; count++) {
- HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
- if (rotate_info->valid) {
- input_buffer = &rotate_info->hw_buffer_info.output_buffer;
- input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
- close_(input_buffer->acquire_fence_fd);
- input_buffer->acquire_fence_fd = -1;
- }
- }
- }
- DLOGI_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
- GetDeviceString(hw_context->type));
- DLOGI_IF(kTagDriverConfig, "retire_fence_fd %d", stack->retire_fence_fd);
- DLOGI_IF(kTagDriverConfig, "*************************************************************");
-
- close_(mdp_commit.release_fence);
-
- return kErrorNone;
-}
-
-void HWFrameBuffer::SetRotatorCtrlParams(HWContext *hw_context, HWLayers *hw_layers) {
- HWRotator *hw_rotator = &hw_context->hw_rotator;
- DLOGV_IF(kTagDriverConfig, "************************* %s Validate Input ************************",
- GetDeviceString(hw_context->type));
-
- hw_rotator->Reset();
-
- mdp_rotation_request *mdp_rot_request = &hw_rotator->mdp_rot_req;
- HWLayersInfo &hw_layer_info = hw_layers->info;
-
- uint32_t &rot_count = mdp_rot_request->count;
- for (uint32_t i = 0; i < hw_layer_info.count; i++) {
- Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
-
- for (uint32_t count = 0; count < 2; count++) {
- HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
-
- if (rotate_info->valid) {
- HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
- mdp_rotation_item *mdp_rot_item = &mdp_rot_request->list[rot_count];
- bool rot90 = (layer.transform.rotation == 90.0f);
-
- if (rot90) {
- mdp_rot_item->flags |= MDP_ROTATION_90;
- }
-
- if (layer.transform.flip_horizontal) {
- mdp_rot_item->flags |= MDP_ROTATION_FLIP_LR;
- }
-
- if (layer.transform.flip_vertical) {
- mdp_rot_item->flags |= MDP_ROTATION_FLIP_UD;
- }
-
- SetRect(rotate_info->src_roi, &mdp_rot_item->src_rect);
- SetRect(rotate_info->dst_roi, &mdp_rot_item->dst_rect);
-
- // TODO(user): Need to assign the writeback id and pipe id returned from resource manager.
- mdp_rot_item->pipe_idx = 0;
- mdp_rot_item->wb_idx = 0;
-
- mdp_rot_item->input.width = layer.input_buffer->width;
- mdp_rot_item->input.height = layer.input_buffer->height;
- SetFormat(layer.input_buffer->format, &mdp_rot_item->input.format);
-
- mdp_rot_item->output.width = rot_buf_info->output_buffer.width;
- mdp_rot_item->output.height = rot_buf_info->output_buffer.height;
- SetFormat(rot_buf_info->output_buffer.format, &mdp_rot_item->output.format);
-
- rot_count++;
-
- DLOGV_IF(kTagDriverConfig, "******************** Layer[%d] %s rotate ********************",
- i, count ? "Right" : "Left");
- DLOGV_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d,\t out_w %d, out_h %d, out_f %d",
- mdp_rot_item->input.width, mdp_rot_item->input.height, mdp_rot_item->input.format,
- mdp_rot_item->output.width, mdp_rot_item->output.height,
- mdp_rot_item->output.format);
- DLOGV_IF(kTagDriverConfig, "pipe_id %d, wb_id %d, rot_flag %d", mdp_rot_item->pipe_idx,
- mdp_rot_item->wb_idx, mdp_rot_item->flags);
- DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_rot_item->src_rect.x,
- mdp_rot_item->src_rect.y, mdp_rot_item->src_rect.w, mdp_rot_item->src_rect.h);
- DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_rot_item->dst_rect.x,
- mdp_rot_item->dst_rect.y, mdp_rot_item->dst_rect.w, mdp_rot_item->dst_rect.h);
- DLOGV_IF(kTagDriverConfig, "*************************************************************");
- }
- }
- }
-}
-
-void HWFrameBuffer::SetRotatorBufferParams(HWContext *hw_context, HWLayers *hw_layers) {
- HWRotator *hw_rotator = &hw_context->hw_rotator;
- mdp_rotation_request *mdp_rot_request = &hw_rotator->mdp_rot_req;
- HWLayersInfo &hw_layer_info = hw_layers->info;
- uint32_t rot_count = 0;
-
- DLOGV_IF(kTagDriverConfig, "************************* %s Commit Input **************************",
- GetDeviceString(hw_context->type));
- DLOGV_IF(kTagDriverConfig, "Rotate layer count is %d", mdp_rot_request->count);
-
- mdp_rot_request->list = hw_rotator->mdp_rot_layers;
-
- for (uint32_t i = 0; i < hw_layer_info.count; i++) {
- Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
-
- for (uint32_t count = 0; count < 2; count++) {
- HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
-
- if (rotate_info->valid) {
- HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
- mdp_rotation_item *mdp_rot_item = &mdp_rot_request->list[rot_count];
-
- mdp_rot_item->input.planes[0].fd = layer.input_buffer->planes[0].fd;
- mdp_rot_item->input.planes[0].offset = layer.input_buffer->planes[0].offset;
- SetStride(hw_context->type, layer.input_buffer->format, layer.input_buffer->width,
- &mdp_rot_item->input.planes[0].stride);
- mdp_rot_item->input.plane_count = 1;
- mdp_rot_item->input.fence = layer.input_buffer->acquire_fence_fd;
-
- mdp_rot_item->output.planes[0].fd = rot_buf_info->output_buffer.planes[0].fd;
- mdp_rot_item->output.planes[0].offset = rot_buf_info->output_buffer.planes[0].offset;
- SetStride(hw_context->type, rot_buf_info->output_buffer.format,
- rot_buf_info->output_buffer.planes[0].stride,
- &mdp_rot_item->output.planes[0].stride);
- mdp_rot_item->output.plane_count = 1;
- mdp_rot_item->output.fence = -1;
-
- rot_count++;
-
- DLOGV_IF(kTagDriverConfig, "******************** Layer[%d] %s rotate ********************",
- i, count ? "Right" : "Left");
- DLOGV_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_stride %d, " \
- "in_plane_count %d, in_fence %d", mdp_rot_item->input.planes[0].fd,
- mdp_rot_item->input.planes[0].offset, mdp_rot_item->input.planes[0].stride,
- mdp_rot_item->input.plane_count, mdp_rot_item->input.fence);
- DLOGV_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, out_plane_count %d, " \
- "out_fence %d", mdp_rot_item->output.planes[0].fd,
- mdp_rot_item->output.planes[0].offset, mdp_rot_item->output.planes[0].stride,
- mdp_rot_item->output.plane_count, mdp_rot_item->output.fence);
- DLOGV_IF(kTagDriverConfig, "*************************************************************");
- }
- }
- }
-}
-
-DisplayError HWFrameBuffer::RotatorValidate(HWContext *hw_context, HWLayers *hw_layers) {
- HWRotator *hw_rotator = &hw_context->hw_rotator;
- SetRotatorCtrlParams(hw_context, hw_layers);
-
- hw_rotator->mdp_rot_req.flags = MDSS_ROTATION_REQUEST_VALIDATE;
- if (ioctl_(hw_context->device_fd, MDSS_ROTATION_REQUEST, &hw_rotator->mdp_rot_req) < 0) {
- IOCTL_LOGE(MDSS_ROTATION_REQUEST, hw_context->type);
- return kErrorHardware;
- }
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::RotatorCommit(HWContext *hw_context, HWLayers *hw_layers) {
- HWRotator *hw_rotator = &hw_context->hw_rotator;
- HWLayersInfo &hw_layer_info = hw_layers->info;
- uint32_t rot_count = 0;
-
- SetRotatorCtrlParams(hw_context, hw_layers);
-
- SetRotatorBufferParams(hw_context, hw_layers);
-
- hw_rotator->mdp_rot_req.flags &= ~MDSS_ROTATION_REQUEST_VALIDATE;
- if (ioctl_(hw_context->device_fd, MDSS_ROTATION_REQUEST, &hw_rotator->mdp_rot_req) < 0) {
- IOCTL_LOGE(MDSS_ROTATION_REQUEST, hw_context->type);
- return kErrorHardware;
- }
-
- for (uint32_t i = 0; i < hw_layer_info.count; i++) {
- Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
-
- layer.input_buffer->release_fence_fd = -1;
-
- for (uint32_t count = 0; count < 2; count++) {
- HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
-
- if (rotate_info->valid) {
- HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
- mdp_rotation_item *mdp_rot_item = &hw_rotator->mdp_rot_req.list[rot_count];
-
- SyncMerge(layer.input_buffer->release_fence_fd, dup(mdp_rot_item->output.fence),
- &layer.input_buffer->release_fence_fd);
-
- rot_buf_info->output_buffer.acquire_fence_fd = dup(mdp_rot_item->output.fence);
-
- close_(mdp_rot_item->output.fence);
- rot_count++;
- }
- }
- }
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::Flush(Handle device) {
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
- HWDisplay *hw_display = &hw_context->hw_display;
-
- switch (hw_context->type) {
- case kDevicePrimary:
- case kDeviceHDMI:
- case kDeviceVirtual:
- {
- hw_display->Reset();
- mdp_layer_commit_v1 &mdp_commit = hw_display->mdp_disp_commit.commit_v1;
- mdp_commit.input_layer_cnt = 0;
- mdp_commit.output_layer = NULL;
-
- mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
- if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) < 0) {
- IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
- DumpLayerCommit(hw_display->mdp_disp_commit);
- return kErrorHardware;
- }
- }
- break;
- default:
- DLOGE("Flush is not supported for the device %s", GetDeviceString(hw_context->type));
- return kErrorNotSupported;
- }
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::SetFormat(const LayerBufferFormat &source, uint32_t *target) {
- switch (source) {
- case kFormatARGB8888: *target = MDP_ARGB_8888; break;
- case kFormatRGBA8888: *target = MDP_RGBA_8888; break;
- case kFormatBGRA8888: *target = MDP_BGRA_8888; break;
- case kFormatRGBX8888: *target = MDP_RGBX_8888; break;
- case kFormatBGRX8888: *target = MDP_BGRX_8888; break;
- case kFormatRGB888: *target = MDP_RGB_888; break;
- case kFormatRGB565: *target = MDP_RGB_565; break;
- case kFormatYCbCr420Planar: *target = MDP_Y_CB_CR_H2V2; break;
- case kFormatYCrCb420Planar: *target = MDP_Y_CR_CB_H2V2; break;
- case kFormatYCbCr420SemiPlanar: *target = MDP_Y_CBCR_H2V2; break;
- case kFormatYCrCb420SemiPlanar: *target = MDP_Y_CRCB_H2V2; break;
- case kFormatYCbCr422Packed: *target = MDP_YCBYCR_H2V1; break;
- case kFormatYCbCr420SemiPlanarVenus: *target = MDP_Y_CBCR_H2V2_VENUS; break;
- case kFormatRGBA8888Ubwc: *target = MDP_RGBA_8888_UBWC; break;
- case kFormatRGB565Ubwc: *target = MDP_RGB_565_UBWC; break;
- case kFormatYCbCr420SPVenusUbwc: *target = MDP_Y_CBCR_H2V2_UBWC; break;
- default:
- DLOGE("Unsupported format type %d", source);
- return kErrorParameters;
- }
-
- return kErrorNone;
-}
-
-DisplayError HWFrameBuffer::SetStride(HWDeviceType device_type, LayerBufferFormat format,
- uint32_t width, uint32_t *target) {
- // TODO(user): This SetStride function is an workaround to satisfy the driver expectation for
- // rotator and virtual devices. Eventually this will be taken care in the driver.
- if (device_type != kDeviceRotator && device_type != kDeviceVirtual) {
- *target = width;
- return kErrorNone;
- }
-
- switch (format) {
- case kFormatARGB8888:
- case kFormatRGBA8888:
- case kFormatBGRA8888:
- case kFormatRGBX8888:
- case kFormatBGRX8888:
- *target = width * 4;
- break;
- case kFormatRGB888:
- *target = width * 3;
- break;
- case kFormatRGB565:
- *target = width * 3;
- break;
- case kFormatYCbCr420SemiPlanarVenus:
- case kFormatYCbCr420SPVenusUbwc:
- case kFormatYCbCr420Planar:
- case kFormatYCrCb420Planar:
- case kFormatYCbCr420SemiPlanar:
- case kFormatYCrCb420SemiPlanar:
- *target = width;
- break;
- case kFormatYCbCr422Packed:
- *target = width * 2;
- break;
- default:
- DLOGE("Unsupported format type %d", format);
- return kErrorParameters;
- }
-
- return kErrorNone;
-}
-
-void HWFrameBuffer::SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target) {
- switch (source) {
- case kBlendingPremultiplied: *target = BLEND_OP_PREMULTIPLIED; break;
- case kBlendingCoverage: *target = BLEND_OP_COVERAGE; break;
- default: *target = BLEND_OP_NOT_DEFINED; break;
- }
-}
-
-void HWFrameBuffer::SetRect(const LayerRect &source, mdp_rect *target) {
- target->x = UINT32(source.left);
- target->y = UINT32(source.top);
- target->w = UINT32(source.right) - target->x;
- target->h = UINT32(source.bottom) - target->y;
-}
-
-void HWFrameBuffer::SyncMerge(const int &fd1, const int &fd2, int *target) {
- if (fd1 >= 0 && fd2 >= 0) {
- buffer_sync_handler_->SyncMerge(fd1, fd2, target);
- } else if (fd1 >= 0) {
- *target = fd1;
- } else if (fd2 >= 0) {
- *target = fd2;
- }
-}
-
-const char *HWFrameBuffer::GetDeviceString(HWDeviceType type) {
- switch (type) {
- case kDevicePrimary:
- return "Primary Display Device";
- case kDeviceHDMI:
- return "HDMI Display Device";
- case kDeviceVirtual:
- return "Virtual Display Device";
- case kDeviceRotator:
- return "Rotator Device";
- default:
- return "Invalid Device";
- }
-}
-
-void* HWFrameBuffer::DisplayEventThread(void *context) {
- if (context) {
- return reinterpret_cast<HWFrameBuffer *>(context)->DisplayEventThreadHandler();
- }
-
- return NULL;
-}
-
-void* HWFrameBuffer::DisplayEventThreadHandler() {
- char data[kMaxStringLength] = {0};
-
- prctl(PR_SET_NAME, event_thread_name_, 0, 0, 0);
- setpriority(PRIO_PROCESS, 0, kThreadPriorityUrgent);
-
- if (fake_vsync_) {
- while (!exit_threads_) {
- // Fake vsync is used only when set explicitly through a property(todo) or when
- // the vsync timestamp node cannot be opened at bootup. There is no
- // fallback to fake vsync from the true vsync loop, ever, as the
- // condition can easily escape detection.
- // Also, fake vsync is delivered only for the primary display.
- usleep(16666);
- STRUCT_VAR(timeval, time_now);
- gettimeofday(&time_now, NULL);
- uint64_t ts = uint64_t(time_now.tv_sec)*1000000000LL +uint64_t(time_now.tv_usec)*1000LL;
-
- // Send Vsync event for primary display(0)
- event_handler_[kDevicePrimary]->VSync(ts);
- }
-
- pthread_exit(0);
- }
-
- typedef void (HWFrameBuffer::*EventHandler)(int, char*);
- EventHandler event_handler[kNumDisplayEvents] = { &HWFrameBuffer::HandleVSync,
- &HWFrameBuffer::HandleBlank,
- &HWFrameBuffer::HandleIdleTimeout };
-
- while (!exit_threads_) {
- int error = poll_(poll_fds_[0], kNumPhysicalDisplays * kNumDisplayEvents, -1);
- if (error < 0) {
- DLOGW("poll failed. error = %s", strerror(errno));
- continue;
- }
-
- for (int display = 0; display < kNumPhysicalDisplays; display++) {
- for (int event = 0; event < kNumDisplayEvents; event++) {
- pollfd &poll_fd = poll_fds_[display][event];
-
- if (poll_fd.revents & POLLPRI) {
- ssize_t length = pread_(poll_fd.fd, data, kMaxStringLength, 0);
- if (length < 0) {
- // If the read was interrupted - it is not a fatal error, just continue.
- DLOGW("pread failed. event = %d, display = %d, error = %s",
- event, display, strerror(errno));
- continue;
- }
-
- (this->*event_handler[event])(display, data);
- }
- }
- }
- }
-
- pthread_exit(0);
-
- return NULL;
-}
-
-void HWFrameBuffer::HandleVSync(int display_id, char *data) {
- int64_t timestamp = 0;
- if (!strncmp(data, "VSYNC=", strlen("VSYNC="))) {
- timestamp = strtoull(data + strlen("VSYNC="), NULL, 0);
- }
- event_handler_[display_id]->VSync(timestamp);
-}
-
-void HWFrameBuffer::HandleBlank(int display_id, char *data) {
- // TODO(user): Need to send blank Event
-}
-
-void HWFrameBuffer::HandleIdleTimeout(int display_id, char *data) {
- event_handler_[display_id]->IdleTimeout();
-}
-
-void HWFrameBuffer::PopulateFBNodeIndex() {
- char stringbuffer[kMaxStringLength];
- DisplayError error = kErrorNone;
- char *line = stringbuffer;
- size_t len = kMaxStringLength;
- ssize_t read;
-
-
- for (int i = 0; i < kDeviceMax; i++) {
- snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_type", fb_path_, i);
- FILE* fileptr = fopen_(stringbuffer, "r");
- if (fileptr == NULL) {
- DLOGW("File not found %s", stringbuffer);
- continue;
- }
- read = getline_(&line, &len, fileptr);
- if (read ==-1) {
- fclose_(fileptr);
- continue;
- }
- // TODO(user): For now, assume primary to be cmd/video/lvds/edp mode panel only
- // Need more concrete info from driver
- if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
- primary_panel_info_.type = kCommandModePanel;
- fb_node_index_[kDevicePrimary] = i;
- } else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) {
- primary_panel_info_.type = kVideoModePanel;
- fb_node_index_[kDevicePrimary] = i;
- } else if ((strncmp(line, "lvds panel", strlen("lvds panel")) == 0)) {
- primary_panel_info_.type = kLVDSPanel;
- fb_node_index_[kDevicePrimary] = i;
- } else if ((strncmp(line, "edp panel", strlen("edp panel")) == 0)) {
- primary_panel_info_.type = kEDPPanel;
- fb_node_index_[kDevicePrimary] = i;
- } else if ((strncmp(line, "dtv panel", strlen("dtv panel")) == 0)) {
- fb_node_index_[kDeviceHDMI] = i;
- } else if ((strncmp(line, "writeback panel", strlen("writeback panel")) == 0)) {
- fb_node_index_[kDeviceVirtual] = i;
- } else {
- DLOGW("Unknown panel type = %s index = %d", line, i);
- }
- fclose_(fileptr);
- }
-}
-
-void HWFrameBuffer::PopulatePanelInfo(int fb_index) {
- char stringbuffer[kMaxStringLength];
- FILE* fileptr = NULL;
- snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_panel_info", fb_path_, fb_index);
- fileptr = fopen_(stringbuffer, "r");
- if (fileptr == NULL) {
- DLOGW("Failed to open msm_fb_panel_info node");
- return;
- }
-
- size_t len = kMaxStringLength;
- ssize_t read;
- char *line = stringbuffer;
- while ((read = getline_(&line, &len, fileptr)) != -1) {
- uint32_t token_count = 0;
- const uint32_t max_count = 10;
- char *tokens[max_count] = { NULL };
- if (!ParseLine(line, tokens, max_count, &token_count)) {
- if (!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
- primary_panel_info_.partial_update = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "xstart", strlen("xstart"))) {
- primary_panel_info_.left_align = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "walign", strlen("walign"))) {
- primary_panel_info_.width_align = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "ystart", strlen("ystart"))) {
- primary_panel_info_.top_align = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "halign", strlen("halign"))) {
- primary_panel_info_.height_align = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "min_w", strlen("min_w"))) {
- primary_panel_info_.min_roi_width = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "min_h", strlen("min_h"))) {
- primary_panel_info_.min_roi_height = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
- primary_panel_info_.needs_roi_merge = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "dynamic_fps_en", strlen("dyn_fps_en"))) {
- primary_panel_info_.dynamic_fps = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
- primary_panel_info_.min_fps = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
- primary_panel_info_.max_fps= atoi(tokens[1]);
- }
- }
- }
- fclose_(fileptr);
-}
-
-// Get SDE HWCapabalities from the sysfs
-DisplayError HWFrameBuffer::PopulateHWCapabilities() {
- DisplayError error = kErrorNone;
- FILE *fileptr = NULL;
- char stringbuffer[kMaxStringLength];
- uint32_t token_count = 0;
- const uint32_t max_count = 10;
- char *tokens[max_count] = { NULL };
- snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/mdp/caps", fb_path_,
- fb_node_index_[kHWPrimary]);
- fileptr = fopen_(stringbuffer, "rb");
-
- if (fileptr == NULL) {
- DLOGE("File '%s' not found", stringbuffer);
- return kErrorHardware;
- }
-
- size_t len = kMaxStringLength;
- ssize_t read;
- char *line = stringbuffer;
- hw_resource_.hw_version = kHWMdssVersion5;
- while ((read = getline_(&line, &len, fileptr)) != -1) {
- // parse the line and update information accordingly
- if (!ParseLine(line, tokens, max_count, &token_count)) {
- if (!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
- hw_resource_.hw_revision = atoi(tokens[1]); // HW Rev, v1/v2
- } else if (!strncmp(tokens[0], "rgb_pipes", strlen("rgb_pipes"))) {
- hw_resource_.num_rgb_pipe = (uint8_t)atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "vig_pipes", strlen("vig_pipes"))) {
- hw_resource_.num_vig_pipe = (uint8_t)atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
- hw_resource_.num_dma_pipe = (uint8_t)atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "cursor_pipes", strlen("cursor_pipes"))) {
- hw_resource_.num_cursor_pipe = (uint8_t)atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "blending_stages", strlen("blending_stages"))) {
- hw_resource_.num_blending_stages = (uint8_t)atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "max_downscale_ratio", strlen("max_downscale_ratio"))) {
- hw_resource_.max_scale_down = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "max_upscale_ratio", strlen("max_upscale_ratio"))) {
- hw_resource_.max_scale_up = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "max_bandwidth_low", strlen("max_bandwidth_low"))) {
- hw_resource_.max_bandwidth_low = atol(tokens[1]);
- } else if (!strncmp(tokens[0], "max_bandwidth_high", strlen("max_bandwidth_high"))) {
- hw_resource_.max_bandwidth_high = atol(tokens[1]);
- } else if (!strncmp(tokens[0], "max_mixer_width", strlen("max_mixer_width"))) {
- hw_resource_.max_mixer_width = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "max_pipe_bw", strlen("max_pipe_bw"))) {
- hw_resource_.max_pipe_bw = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "max_mdp_clk", strlen("max_mdp_clk"))) {
- hw_resource_.max_sde_clk = atoi(tokens[1]);
- } else if (!strncmp(tokens[0], "clk_fudge_factor", strlen("clk_fudge_factor"))) {
- hw_resource_.clk_fudge_factor = FLOAT(atoi(tokens[1])) / FLOAT(atoi(tokens[2]));
- } else if (!strncmp(tokens[0], "features", strlen("features"))) {
- for (uint32_t i = 0; i < token_count; i++) {
- if (!strncmp(tokens[i], "bwc", strlen("bwc"))) {
- hw_resource_.has_bwc = true;
- } else if (!strncmp(tokens[i], "decimation", strlen("decimation"))) {
- hw_resource_.has_decimation = true;
- } else if (!strncmp(tokens[i], "tile_format", strlen("tile_format"))) {
- hw_resource_.has_macrotile = true;
- } else if (!strncmp(tokens[i], "src_split", strlen("src_split"))) {
- hw_resource_.is_src_split = true;
- } else if (!strncmp(tokens[i], "non_scalar_rgb", strlen("non_scalar_rgb"))) {
- hw_resource_.has_non_scalar_rgb = true;
- } else if (!strncmp(tokens[i], "rotator_downscale", strlen("rotator_downscale"))) {
- hw_resource_.has_rotator_downscale = true;
- }
- }
- }
- }
- }
- fclose_(fileptr);
-
- // Split info - for MDSS Version 5 - No need to check version here
- snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/msm_fb_split", fb_path_,
- fb_node_index_[kHWPrimary]);
- fileptr = fopen_(stringbuffer, "r");
- if (fileptr) {
- // Format "left right" space as delimiter
- read = getline_(&line, &len, fileptr);
- if (read != -1) {
- if (!ParseLine(line, tokens, max_count, &token_count)) {
- hw_resource_.split_info.left_split = atoi(tokens[0]);
- hw_resource_.split_info.right_split = atoi(tokens[1]);
- }
- }
- fclose_(fileptr);
- }
-
- // SourceSplit enabled - Get More information
- if (hw_resource_.is_src_split) {
- snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/msm_fb_src_split_info", fb_path_,
- fb_node_index_[kHWPrimary]);
- fileptr = fopen_(stringbuffer, "r");
- if (fileptr) {
- read = getline_(&line, &len, fileptr);
- if (read != -1) {
- if (!strncmp(line, "src_split_always", strlen("src_split_always"))) {
- hw_resource_.always_src_split = true;
- }
- }
- fclose_(fileptr);
- }
- }
-
- DLOGI("SDE Version = %d, SDE Revision = %x, RGB = %d, VIG = %d, DMA = %d, Cursor = %d",
- hw_resource_.hw_version, hw_resource_.hw_revision, hw_resource_.num_rgb_pipe,
- hw_resource_.num_vig_pipe, hw_resource_.num_dma_pipe, hw_resource_.num_cursor_pipe);
- DLOGI("Upscale Ratio = %d, Downscale Ratio = %d, Blending Stages = %d", hw_resource_.max_scale_up,
- hw_resource_.max_scale_down, hw_resource_.num_blending_stages);
- DLOGI("BWC = %d, Decimation = %d, Tile Format = %d, Rotator Downscale = %d", hw_resource_.has_bwc,
- hw_resource_.has_decimation, hw_resource_.has_macrotile,
- hw_resource_.has_rotator_downscale);
- DLOGI("Left Split = %d, Right Split = %d", hw_resource_.split_info.left_split,
- hw_resource_.split_info.right_split);
- DLOGI("SourceSplit = %d, Always = %d", hw_resource_.is_src_split, hw_resource_.always_src_split);
- DLOGI("MaxLowBw = %"PRIu64", MaxHighBw = %"PRIu64"", hw_resource_.max_bandwidth_low,
- hw_resource_.max_bandwidth_high);
- DLOGI("MaxPipeBw = %"PRIu64" KBps, MaxSDEClock = %"PRIu64" Hz, ClockFudgeFactor = %f",
- hw_resource_.max_pipe_bw, hw_resource_.max_sde_clk, hw_resource_.clk_fudge_factor);
-
- return error;
-}
-
-int HWFrameBuffer::ParseLine(char *input, char *tokens[], const uint32_t max_token,
- uint32_t *count) {
- char *tmp_token = NULL;
- char *temp_ptr;
- uint32_t index = 0;
- const char *delim = ", =\n";
- if (!input) {
- return -1;
- }
- tmp_token = strtok_r(input, delim, &temp_ptr);
- while (tmp_token && index < max_token) {
- tokens[index++] = tmp_token;
- tmp_token = strtok_r(NULL, delim, &temp_ptr);
- }
- *count = index;
-
- return 0;
-}
-
-bool HWFrameBuffer::EnableHotPlugDetection(int enable) {
- bool ret_value = true;
- char hpdpath[kMaxStringLength];
- snprintf(hpdpath , sizeof(hpdpath), "%s%d/hpd", fb_path_, fb_node_index_[kDeviceHDMI]);
- int hpdfd = open_(hpdpath, O_RDWR, 0);
- if (hpdfd < 0) {
- DLOGE("Open failed = %s", hpdpath);
- return kErrorHardware;
- }
- char value = enable ? '1' : '0';
- ssize_t length = pwrite_(hpdfd, &value, 1, 0);
- if (length <= 0) {
- DLOGE("Write failed 'hpd' = %d", enable);
- ret_value = false;
- }
- close_(hpdfd);
-
- return ret_value;
-}
-
-int HWFrameBuffer::GetHDMIModeCount() {
- ssize_t length = -1;
- char edid_str[256] = {'\0'};
- char edid_path[kMaxStringLength] = {'\0'};
- snprintf(edid_path, sizeof(edid_path), "%s%d/edid_modes", fb_path_, fb_node_index_[kHWHDMI]);
- int edid_file = open_(edid_path, O_RDONLY);
- if (edid_file < 0) {
- DLOGE("EDID file open failed.");
- return -1;
- }
-
- length = pread_(edid_file, edid_str, sizeof(edid_str)-1, 0);
- if (length <= 0) {
- DLOGE("%s: edid_modes file empty");
- edid_str[0] = '\0';
- } else {
- DLOGI("EDID mode string: %s", edid_str);
- while (length > 1 && isspace(edid_str[length-1])) {
- --length;
- }
- edid_str[length] = '\0';
- }
- close_(edid_file);
-
- if (length > 0) {
- // Get EDID modes from the EDID string
- char *ptr = edid_str;
- const uint32_t edid_count_max = 128;
- char *tokens[edid_count_max] = { NULL };
- ParseLine(ptr, tokens, edid_count_max, &hdmi_mode_count_);
- for (uint32_t i = 0; i < hdmi_mode_count_; i++) {
- hdmi_modes_[i] = atoi(tokens[i]);
- }
- }
- return (hdmi_mode_count_ > 0) ? hdmi_mode_count_ : 0;
-}
-
-bool HWFrameBuffer::MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode,
- fb_var_screeninfo *info) {
- if (!mode || !info) {
- return false;
- }
-
- info->reserved[0] = 0;
- info->reserved[1] = 0;
- info->reserved[2] = 0;
- info->reserved[3] = (info->reserved[3] & 0xFFFF) | (mode->video_format << 16);
- info->xoffset = 0;
- info->yoffset = 0;
- info->xres = mode->active_h;
- info->yres = mode->active_v;
- info->pixclock = (mode->pixel_freq) * 1000;
- info->vmode = mode->interlaced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
- info->right_margin = mode->front_porch_h;
- info->hsync_len = mode->pulse_width_h;
- info->left_margin = mode->back_porch_h;
- info->lower_margin = mode->front_porch_v;
- info->vsync_len = mode->pulse_width_v;
- info->upper_margin = mode->back_porch_v;
-
- return true;
-}
-
-void HWFrameBuffer::SetIdleTimeoutMs(Handle device, uint32_t timeout_ms) {
- char node_path[kMaxStringLength] = {0};
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
-
- DLOGI("idle timeout = %d ms", timeout_ms);
-
- switch (hw_context->type) {
- case kDevicePrimary:
- {
- // Idle fallback feature is supported only for video mode panel.
- if (primary_panel_info_.type == kCommandModePanel) {
- return;
- }
-
- snprintf(node_path, sizeof(node_path), "%s%d/idle_time", fb_path_,
- fb_node_index_[hw_context->type]);
-
- // Open a sysfs node to send the timeout value to driver.
- int fd = open_(node_path, O_WRONLY);
- if (fd < 0) {
- DLOGE("Unable to open %s, node %s", node_path, strerror(errno));
- return;
- }
-
- char timeout_string[64];
- snprintf(timeout_string, sizeof(timeout_string), "%d", timeout_ms);
-
- // Notify driver about the timeout value
- ssize_t length = pwrite_(fd, timeout_string, strlen(timeout_string), 0);
- if (length < -1) {
- DLOGE("Unable to write into %s, node %s", node_path, strerror(errno));
- }
-
- close_(fd);
- }
- break;
- default:
- break;
- }
-}
-
-} // namespace sde
-
diff --git a/displayengine/libs/core/hw_framebuffer.h b/displayengine/libs/core/hw_framebuffer.h
deleted file mode 100644
index b2a37ab..0000000
--- a/displayengine/libs/core/hw_framebuffer.h
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
-* Copyright (c) 2014 - 2015, 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 __HW_FRAMEBUFFER_H__
-#define __HW_FRAMEBUFFER_H__
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <linux/msm_mdp_ext.h>
-#include <video/msm_hdmi_modes.h>
-#include <linux/mdss_rotator.h>
-#include <poll.h>
-#include <pthread.h>
-
-#include "hw_interface.h"
-
-namespace sde {
-
-class HWFrameBuffer : public HWInterface {
- public:
- explicit HWFrameBuffer(BufferSyncHandler *buffer_sync_handler);
- DisplayError Init();
- DisplayError Deinit();
- virtual DisplayError GetHWCapabilities(HWResourceInfo *hw_res_info);
- virtual DisplayError Open(HWDeviceType type, Handle *device, HWEventHandler *eventhandler);
- virtual DisplayError Close(Handle device);
- virtual DisplayError GetNumDisplayAttributes(Handle device, uint32_t *count);
- virtual DisplayError GetDisplayAttributes(Handle device, HWDisplayAttributes *display_attributes,
- uint32_t index);
- virtual DisplayError SetDisplayAttributes(Handle device, uint32_t index);
- virtual DisplayError GetConfigIndex(Handle device, uint32_t mode, uint32_t *index);
- virtual DisplayError PowerOn(Handle device);
- virtual DisplayError PowerOff(Handle device);
- virtual DisplayError Doze(Handle device);
- virtual DisplayError SetVSyncState(Handle device, bool enable);
- virtual DisplayError Standby(Handle device);
- virtual DisplayError OpenRotatorSession(Handle device, HWRotateInfo *rotate_info);
- virtual DisplayError CloseRotatorSession(Handle device, int32_t session_id);
- virtual DisplayError Validate(Handle device, HWLayers *hw_layers);
- virtual DisplayError Commit(Handle device, HWLayers *hw_layers);
- virtual DisplayError Flush(Handle device);
- virtual void SetIdleTimeoutMs(Handle device, uint32_t timeout_ms);
-
- private:
- struct HWDisplay {
- mdp_layer_commit mdp_disp_commit;
- mdp_input_layer mdp_in_layers[kMaxSDELayers * 2]; // split panel (left + right)
- mdp_scale_data scale_data[kMaxSDELayers * 2];
- mdp_output_layer mdp_out_layer;
-
- HWDisplay() { Reset(); }
-
- void Reset() {
- memset(&mdp_disp_commit, 0, sizeof(mdp_disp_commit));
- memset(&mdp_in_layers, 0, sizeof(mdp_in_layers));
- memset(&mdp_out_layer, 0, sizeof(mdp_out_layer));
- memset(&scale_data, 0, sizeof(scale_data));
-
- for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
- mdp_in_layers[i].buffer.fence = -1;
- }
-
- mdp_disp_commit.version = MDP_COMMIT_VERSION_1_0;
- mdp_disp_commit.commit_v1.input_layers = mdp_in_layers;
- mdp_disp_commit.commit_v1.output_layer = &mdp_out_layer;
- mdp_disp_commit.commit_v1.release_fence = -1;
- mdp_disp_commit.commit_v1.retire_fence = -1;
- }
-
- mdp_scale_data* GetScaleDataRef(uint32_t index) { return &scale_data[index]; }
- };
-
- struct HWRotator {
- struct mdp_rotation_request mdp_rot_req;
- struct mdp_rotation_item mdp_rot_layers[kMaxSDELayers * 2]; // split panel (left + right)
-
- HWRotator() { Reset(); }
-
- void Reset() {
- memset(&mdp_rot_req, 0, sizeof(mdp_rot_req));
- memset(&mdp_rot_layers, 0, sizeof(mdp_rot_layers));
-
- for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
- mdp_rot_layers[i].input.fence = -1;
- mdp_rot_layers[i].output.fence = -1;
- }
-
- mdp_rot_req.version = MDP_ROTATION_REQUEST_VERSION_1_0;
- mdp_rot_req.list = mdp_rot_layers;
- }
- };
-
- struct HWContext {
- HWDeviceType type;
- int device_fd;
- HWRotator hw_rotator;
- HWDisplay hw_display;
-
- HWContext() : type(kDeviceMax), device_fd(-1) { }
- };
-
- enum PanelType {
- kNoPanel,
- kCommandModePanel,
- kVideoModePanel,
- kDTvPanel,
- kWriteBackPanel,
- kLVDSPanel,
- kEDPPanel,
- };
-
- enum {
- kHWEventVSync,
- kHWEventBlank,
- };
-
- // Maps to the msm_fb_panel_info
- struct PanelInfo {
- PanelType type; // Smart or Dumb
- bool partial_update; // Partial update feature
- int left_align; // ROI left alignment restriction
- int width_align; // ROI width alignment restriction
- int top_align;; // ROI top alignment restriction
- int height_align; // ROI height alignment restriction
- int min_roi_width; // Min width needed for ROI
- int min_roi_height; // Min height needed for ROI
- bool needs_roi_merge; // Merge ROI's of both the DSI's
- bool dynamic_fps; // Panel Supports dynamic fps
- uint32_t min_fps; // Min fps supported by panel
- uint32_t max_fps; // Max fps supported by panel
-
- PanelInfo() : type(kNoPanel), partial_update(false), left_align(false), width_align(false),
- top_align(false), height_align(false), min_roi_width(0), min_roi_height(0),
- needs_roi_merge(false), dynamic_fps(false), min_fps(0), max_fps(0) { }
- };
-
- static const int kMaxStringLength = 1024;
- static const int kNumPhysicalDisplays = 2;
- static const int kNumDisplayEvents = 3;
- static const int kHWMdssVersion5 = 500; // MDSS_V5
-
- DisplayError DisplayValidate(HWContext *device_ctx, HWLayers *hw_layers);
- DisplayError DisplayCommit(HWContext *device_ctx, HWLayers *hw_layers);
-
- void SetRotatorCtrlParams(HWContext *device_ctx, HWLayers *hw_layers);
- void SetRotatorBufferParams(HWContext *device_ctx, HWLayers *hw_layers);
-
- DisplayError RotatorValidate(HWContext *device_ctx, HWLayers *hw_layers);
- DisplayError RotatorCommit(HWContext *device_ctx, HWLayers *hw_layers);
- void DumpLayerCommit(mdp_layer_commit &layer_commit);
- inline DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
- inline DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format,
- uint32_t width, uint32_t *target);
- inline void SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target);
- inline void SetRect(const LayerRect &source, mdp_rect *target);
- inline void SyncMerge(const int &fd1, const int &fd2, int *target);
-
- inline const char *GetDeviceString(HWDeviceType type);
-
- // Event Thread to receive vsync/blank events
- static void* DisplayEventThread(void *context);
- void* DisplayEventThreadHandler();
-
- void HandleVSync(int display_id, char *data);
- void HandleBlank(int display_id, char *data);
- void HandleIdleTimeout(int display_id, char *data);
-
- // Populates HW FrameBuffer Node Index
- void PopulateFBNodeIndex();
- // Populates the Panel Info based on node index
- void PopulatePanelInfo(int fb_index);
- // Populates HW Capabilities
- DisplayError PopulateHWCapabilities();
- int ParseLine(char *input, char *token[], const uint32_t max_token, uint32_t *count);
-
- // HDMI Related Functions
- bool EnableHotPlugDetection(int enable);
- int GetHDMIModeCount();
- bool MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode, fb_var_screeninfo *info);
-
- // Pointers to system calls which are either mapped to actual system call or virtual driver.
- int (*ioctl_)(int, int, ...);
- int (*open_)(const char *, int, ...);
- int (*close_)(int);
- int (*poll_)(struct pollfd *, nfds_t, int);
- ssize_t (*pread_)(int, void *, size_t, off_t);
- ssize_t (*pwrite_)(int, const void *, size_t, off_t);
- FILE* (*fopen_)( const char *fname, const char *mode);
- int (*fclose_)(FILE* fileptr);
- ssize_t (*getline_)(char **lineptr, size_t *linelen, FILE *stream);
-
- // Store the Device EventHandlers - used for callback
- HWEventHandler *event_handler_[kNumPhysicalDisplays];
- pollfd poll_fds_[kNumPhysicalDisplays][kNumDisplayEvents];
- pthread_t event_thread_;
- const char *event_thread_name_;
- bool fake_vsync_;
- bool exit_threads_;
- HWResourceInfo hw_resource_;
- int fb_node_index_[kDeviceMax];
- const char* fb_path_;
- PanelInfo primary_panel_info_;
- bool hotplug_enabled_;
- uint32_t hdmi_mode_count_;
- uint32_t hdmi_modes_[256];
- // Holds the hdmi timing information. Ex: resolution, fps etc.,
- msm_hdmi_mode_timing_info *supported_video_modes_;
- BufferSyncHandler *buffer_sync_handler_;
-};
-
-} // namespace sde
-
-#endif // __HW_FRAMEBUFFER_H__
-
diff --git a/displayengine/libs/core/hw_interface.cpp b/displayengine/libs/core/hw_hdmi_interface.h
similarity index 67%
copy from displayengine/libs/core/hw_interface.cpp
copy to displayengine/libs/core/hw_hdmi_interface.h
index 6b99a73..36ca991 100644
--- a/displayengine/libs/core/hw_interface.cpp
+++ b/displayengine/libs/core/hw_hdmi_interface.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015, 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:
@@ -22,34 +22,26 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <utils/constants.h>
+#ifndef __HW_HDMI_INTERFACE_H__
+#define __HW_HDMI_INTERFACE_H__
#include "hw_interface.h"
-#include "hw_framebuffer.h"
namespace sde {
-DisplayError HWInterface::Create(HWInterface **intf, BufferSyncHandler *buffer_sync_handler) {
- DisplayError error = kErrorNone;
- HWFrameBuffer *hw_frame_buffer = NULL;
+class HWInfoInterface;
- hw_frame_buffer = new HWFrameBuffer(buffer_sync_handler);
- error = hw_frame_buffer->Init();
- if (UNLIKELY(error != kErrorNone)) {
- delete hw_frame_buffer;
- } else {
- *intf = hw_frame_buffer;
- }
+class HWHDMIInterface: virtual public HWInterface {
+ public:
+ static DisplayError Create(HWHDMIInterface **intf, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler);
+ static DisplayError Destroy(HWHDMIInterface *intf);
- return error;
-}
-
-DisplayError HWInterface::Destroy(HWInterface *intf) {
- HWFrameBuffer *hw_frame_buffer = static_cast<HWFrameBuffer *>(intf);
- hw_frame_buffer->Deinit();
- delete hw_frame_buffer;
- return kErrorNone;
-}
+ protected:
+ virtual ~HWHDMIInterface() { }
+};
} // namespace sde
+#endif // __HW_HDMI_INTERFACE_H__
+
diff --git a/displayengine/libs/core/hw_interface.cpp b/displayengine/libs/core/hw_info_interface.h
similarity index 69%
rename from displayengine/libs/core/hw_interface.cpp
rename to displayengine/libs/core/hw_info_interface.h
index 6b99a73..035db40 100644
--- a/displayengine/libs/core/hw_interface.cpp
+++ b/displayengine/libs/core/hw_info_interface.h
@@ -22,34 +22,25 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <utils/constants.h>
+#ifndef __HW_INFO_INTERFACE_H__
+#define __HW_INFO_INTERFACE_H__
-#include "hw_interface.h"
-#include "hw_framebuffer.h"
+#include <inttypes.h>
+#include <private/hw_info_types.h>
namespace sde {
-DisplayError HWInterface::Create(HWInterface **intf, BufferSyncHandler *buffer_sync_handler) {
- DisplayError error = kErrorNone;
- HWFrameBuffer *hw_frame_buffer = NULL;
+class HWInfoInterface {
+ public:
+ static DisplayError Create(HWInfoInterface **intf);
+ static DisplayError Destroy(HWInfoInterface *intf);
+ virtual DisplayError GetHWResourceInfo(HWResourceInfo *hw_resource) = 0;
- hw_frame_buffer = new HWFrameBuffer(buffer_sync_handler);
- error = hw_frame_buffer->Init();
- if (UNLIKELY(error != kErrorNone)) {
- delete hw_frame_buffer;
- } else {
- *intf = hw_frame_buffer;
- }
-
- return error;
-}
-
-DisplayError HWInterface::Destroy(HWInterface *intf) {
- HWFrameBuffer *hw_frame_buffer = static_cast<HWFrameBuffer *>(intf);
- hw_frame_buffer->Deinit();
- delete hw_frame_buffer;
- return kErrorNone;
-}
+ protected:
+ virtual ~HWInfoInterface() { }
+};
} // namespace sde
+#endif // __HW_INFO_INTERFACE_H__
+
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index 0d1634c..e8e0c63 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -27,6 +27,7 @@
#include <core/display_interface.h>
#include <private/strategy_interface.h>
+#include <private/hw_info_types.h>
#include <utils/constants.h>
#include <core/buffer_allocator.h>
#include <core/buffer_sync_handler.h>
@@ -42,61 +43,6 @@
kHWBlockMax
};
-enum HWDeviceType {
- kDevicePrimary,
- kDeviceHDMI,
- kDeviceVirtual,
- kDeviceRotator,
- kDeviceMax,
-};
-
-struct HWResourceInfo {
- uint32_t hw_version;
- uint32_t hw_revision;
- uint32_t num_dma_pipe;
- uint32_t num_vig_pipe;
- uint32_t num_rgb_pipe;
- uint32_t num_cursor_pipe;
- uint32_t num_blending_stages;
- uint32_t num_rotator;
- uint32_t num_control;
- uint32_t num_mixer_to_disp;
- uint32_t smp_total;
- uint32_t smp_size;
- uint32_t num_smp_per_pipe;
- uint32_t max_scale_up;
- uint32_t max_scale_down;
- uint64_t max_bandwidth_low;
- uint64_t max_bandwidth_high;
- uint32_t max_mixer_width;
- uint32_t max_pipe_bw;
- uint32_t max_sde_clk;
- float clk_fudge_factor;
- struct SplitInfo {
- uint32_t left_split;
- uint32_t right_split;
- SplitInfo() : left_split(0), right_split(0) { }
- } split_info;
- bool has_bwc;
- bool has_decimation;
- bool has_macrotile;
- bool has_rotator_downscale;
- bool has_non_scalar_rgb;
- bool is_src_split;
- bool always_src_split;
-
- HWResourceInfo()
- : hw_version(0), hw_revision(0), num_dma_pipe(0), num_vig_pipe(0), num_rgb_pipe(0),
- num_cursor_pipe(0), num_blending_stages(0), num_rotator(0), num_control(0),
- num_mixer_to_disp(0), smp_total(0), smp_size(0), num_smp_per_pipe(0), max_scale_up(1),
- max_scale_down(1), max_bandwidth_low(0), max_bandwidth_high(0), max_mixer_width(2048),
- max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false),
- has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
- has_non_scalar_rgb(false), is_src_split(false), always_src_split(false) { }
-
- void Reset() { *this = HWResourceInfo(); }
-};
-
struct HWBufferInfo : public BufferInfo {
LayerBuffer output_buffer;
int session_id;
@@ -164,8 +110,9 @@
struct HWDisplayAttributes : DisplayConfigVariableInfo {
bool is_device_split;
uint32_t split_left;
+ bool always_src_split;
- HWDisplayAttributes() : is_device_split(false), split_left(0) { }
+ HWDisplayAttributes() : is_device_split(false), split_left(0), always_src_split(false) { }
void Reset() { *this = HWDisplayAttributes(); }
};
@@ -182,27 +129,21 @@
class HWInterface {
public:
- static DisplayError Create(HWInterface **intf, BufferSyncHandler *buffer_sync_handler);
- static DisplayError Destroy(HWInterface *intf);
- virtual DisplayError GetHWCapabilities(HWResourceInfo *hw_res_info) = 0;
- virtual DisplayError Open(HWDeviceType type, Handle *device, HWEventHandler *eventhandler) = 0;
- virtual DisplayError Close(Handle device) = 0;
- virtual DisplayError GetNumDisplayAttributes(Handle device, uint32_t *count) = 0;
- virtual DisplayError GetDisplayAttributes(Handle device,
- HWDisplayAttributes *display_attributes, uint32_t index) = 0;
- virtual DisplayError SetDisplayAttributes(Handle device, uint32_t index) = 0;
- virtual DisplayError GetConfigIndex(Handle device, uint32_t mode, uint32_t *index) = 0;
- virtual DisplayError PowerOn(Handle device) = 0;
- virtual DisplayError PowerOff(Handle device) = 0;
- virtual DisplayError Doze(Handle device) = 0;
- virtual DisplayError SetVSyncState(Handle device, bool enable) = 0;
- virtual DisplayError Standby(Handle device) = 0;
- virtual DisplayError OpenRotatorSession(Handle device, HWRotateInfo *rotate_info) = 0;
- virtual DisplayError CloseRotatorSession(Handle device, int32_t session_id) = 0;
- virtual DisplayError Validate(Handle device, HWLayers *hw_layers) = 0;
- virtual DisplayError Commit(Handle device, HWLayers *hw_layers) = 0;
- virtual DisplayError Flush(Handle device) = 0;
- virtual void SetIdleTimeoutMs(Handle device, uint32_t timeout_ms) = 0;
+ virtual DisplayError Open(HWEventHandler *eventhandler) = 0;
+ virtual DisplayError Close() = 0;
+ virtual DisplayError GetNumDisplayAttributes(uint32_t *count) = 0;
+ virtual DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+ uint32_t index) = 0;
+ virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info) = 0;
+ virtual DisplayError SetDisplayAttributes(uint32_t index) = 0;
+ virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index) = 0;
+ virtual DisplayError PowerOn() = 0;
+ virtual DisplayError PowerOff() = 0;
+ virtual DisplayError Doze() = 0;
+ virtual DisplayError Standby() = 0;
+ virtual DisplayError Validate(HWLayers *hw_layers) = 0;
+ virtual DisplayError Commit(HWLayers *hw_layers) = 0;
+ virtual DisplayError Flush() = 0;
protected:
virtual ~HWInterface() { }
diff --git a/displayengine/libs/core/hw_interface.cpp b/displayengine/libs/core/hw_primary_interface.h
similarity index 66%
copy from displayengine/libs/core/hw_interface.cpp
copy to displayengine/libs/core/hw_primary_interface.h
index 6b99a73..31df694 100644
--- a/displayengine/libs/core/hw_interface.cpp
+++ b/displayengine/libs/core/hw_primary_interface.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015, 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:
@@ -22,34 +22,27 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <utils/constants.h>
-
-#include "hw_interface.h"
-#include "hw_framebuffer.h"
+#ifndef __HW_PRIMARY_INTERFACE_H__
+#define __HW_PRIMARY_INTERFACE_H__
namespace sde {
-DisplayError HWInterface::Create(HWInterface **intf, BufferSyncHandler *buffer_sync_handler) {
- DisplayError error = kErrorNone;
- HWFrameBuffer *hw_frame_buffer = NULL;
+class BufferSyncHandler;
+class HWInfoInterface;
- hw_frame_buffer = new HWFrameBuffer(buffer_sync_handler);
- error = hw_frame_buffer->Init();
- if (UNLIKELY(error != kErrorNone)) {
- delete hw_frame_buffer;
- } else {
- *intf = hw_frame_buffer;
- }
+class HWPrimaryInterface: virtual public HWInterface {
+ public:
+ static DisplayError Create(HWPrimaryInterface **intf, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler);
+ static DisplayError Destroy(HWPrimaryInterface *intf);
+ virtual DisplayError SetVSyncState(bool enable) = 0;
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms) = 0;
- return error;
-}
-
-DisplayError HWInterface::Destroy(HWInterface *intf) {
- HWFrameBuffer *hw_frame_buffer = static_cast<HWFrameBuffer *>(intf);
- hw_frame_buffer->Deinit();
- delete hw_frame_buffer;
- return kErrorNone;
-}
+ protected:
+ virtual ~HWPrimaryInterface() { }
+};
} // namespace sde
+#endif // __HW_PRIMARY_INTERFACE_H__
+
diff --git a/displayengine/libs/core/hw_interface.cpp b/displayengine/libs/core/hw_rotator_interface.h
similarity index 65%
copy from displayengine/libs/core/hw_interface.cpp
copy to displayengine/libs/core/hw_rotator_interface.h
index 6b99a73..35876d6 100644
--- a/displayengine/libs/core/hw_interface.cpp
+++ b/displayengine/libs/core/hw_rotator_interface.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015, 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:
@@ -22,34 +22,31 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <utils/constants.h>
-
-#include "hw_interface.h"
-#include "hw_framebuffer.h"
+#ifndef __HW_ROTATOR_INTERFACE_H__
+#define __HW_ROTATOR_INTERFACE_H__
namespace sde {
-DisplayError HWInterface::Create(HWInterface **intf, BufferSyncHandler *buffer_sync_handler) {
- DisplayError error = kErrorNone;
- HWFrameBuffer *hw_frame_buffer = NULL;
+class BufferSyncHandler;
+struct HWRotateInfo;
+struct HWLayers;
- hw_frame_buffer = new HWFrameBuffer(buffer_sync_handler);
- error = hw_frame_buffer->Init();
- if (UNLIKELY(error != kErrorNone)) {
- delete hw_frame_buffer;
- } else {
- *intf = hw_frame_buffer;
- }
+class HWRotatorInterface {
+ public:
+ static DisplayError Create(HWRotatorInterface **intf, BufferSyncHandler *buffer_sync_handler);
+ static DisplayError Destroy(HWRotatorInterface *intf);
+ virtual DisplayError Open() = 0;
+ virtual DisplayError Close() = 0;
+ virtual DisplayError OpenSession(HWRotateInfo *rotate_info) = 0;
+ virtual DisplayError CloseSession(int32_t session_id) = 0;
+ virtual DisplayError Validate(HWLayers *hw_layers) = 0;
+ virtual DisplayError Commit(HWLayers *hw_layers) = 0;
- return error;
-}
-
-DisplayError HWInterface::Destroy(HWInterface *intf) {
- HWFrameBuffer *hw_frame_buffer = static_cast<HWFrameBuffer *>(intf);
- hw_frame_buffer->Deinit();
- delete hw_frame_buffer;
- return kErrorNone;
-}
+ protected:
+ virtual ~HWRotatorInterface() { }
+};
} // namespace sde
+#endif // __HW_ROTATOR_INTERFACE_H__
+
diff --git a/displayengine/libs/core/hw_interface.cpp b/displayengine/libs/core/hw_virtual_interface.h
similarity index 67%
copy from displayengine/libs/core/hw_interface.cpp
copy to displayengine/libs/core/hw_virtual_interface.h
index 6b99a73..6976955 100644
--- a/displayengine/libs/core/hw_interface.cpp
+++ b/displayengine/libs/core/hw_virtual_interface.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015, 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:
@@ -22,34 +22,26 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <utils/constants.h>
+#ifndef __HW_VIRTUAL_INTERFACE_H__
+#define __HW_VIRTUAL_INTERFACE_H__
#include "hw_interface.h"
-#include "hw_framebuffer.h"
namespace sde {
-DisplayError HWInterface::Create(HWInterface **intf, BufferSyncHandler *buffer_sync_handler) {
- DisplayError error = kErrorNone;
- HWFrameBuffer *hw_frame_buffer = NULL;
+class HWInfoInterface;
- hw_frame_buffer = new HWFrameBuffer(buffer_sync_handler);
- error = hw_frame_buffer->Init();
- if (UNLIKELY(error != kErrorNone)) {
- delete hw_frame_buffer;
- } else {
- *intf = hw_frame_buffer;
- }
+class HWVirtualInterface: virtual public HWInterface {
+ public:
+ static DisplayError Create(HWVirtualInterface **intf, HWInfoInterface *hw_info_intf,
+ BufferSyncHandler *buffer_sync_handler);
+ static DisplayError Destroy(HWVirtualInterface *intf);
- return error;
-}
-
-DisplayError HWInterface::Destroy(HWInterface *intf) {
- HWFrameBuffer *hw_frame_buffer = static_cast<HWFrameBuffer *>(intf);
- hw_frame_buffer->Deinit();
- delete hw_frame_buffer;
- return kErrorNone;
-}
+ protected:
+ virtual ~HWVirtualInterface() { }
+};
} // namespace sde
+#endif // __HW_VIRTUAL_INTERFACE_H__
+
diff --git a/displayengine/libs/core/offline_ctrl.cpp b/displayengine/libs/core/offline_ctrl.cpp
index 8794074..b7d5eef 100644
--- a/displayengine/libs/core/offline_ctrl.cpp
+++ b/displayengine/libs/core/offline_ctrl.cpp
@@ -26,6 +26,9 @@
#include <utils/debug.h>
#include "offline_ctrl.h"
+#include "hw_rotator_interface.h"
+#include <core/buffer_sync_handler.h>
+#include "hw_interface.h"
#define __CLASS__ "OfflineCtrl"
@@ -33,16 +36,25 @@
// TODO(user): Move this offline controller under composition manager like other modules
// [resource manager]. Implement session management and buffer management in offline controller.
-OfflineCtrl::OfflineCtrl() : hw_intf_(NULL), hw_rotator_device_(NULL) {
+OfflineCtrl::OfflineCtrl() : hw_rotator_intf_(NULL), hw_rotator_present_(false) {
}
-DisplayError OfflineCtrl::Init(HWInterface *hw_intf, HWResourceInfo hw_res_info) {
- hw_intf_ = hw_intf;
+DisplayError OfflineCtrl::Init(BufferSyncHandler *buffer_sync_handler) {
DisplayError error = kErrorNone;
- error = hw_intf_->Open(kDeviceRotator, &hw_rotator_device_, NULL);
+ error = HWRotatorInterface::Create(&hw_rotator_intf_, buffer_sync_handler);
+ if (error != kErrorNone) {
+ if (hw_rotator_intf_) {
+ HWRotatorInterface::Destroy(hw_rotator_intf_);
+ }
+ return error;
+ }
+
+ error = hw_rotator_intf_->Open();
if (error != kErrorNone) {
DLOGW("Failed to open rotator device");
+ } else {
+ hw_rotator_present_ = true;
}
return kErrorNone;
@@ -51,11 +63,13 @@
DisplayError OfflineCtrl::Deinit() {
DisplayError error = kErrorNone;
- error = hw_intf_->Close(hw_rotator_device_);
+ error = hw_rotator_intf_->Close();
if (error != kErrorNone) {
DLOGW("Failed to close rotator device");
return error;
}
+ hw_rotator_present_ = false;
+ HWRotatorInterface::Destroy(hw_rotator_intf_);
return kErrorNone;
}
@@ -87,13 +101,13 @@
disp_offline_ctx->pending_rot_commit = false;
- if (!hw_rotator_device_ && IsRotationRequired(hw_layers)) {
+ if (!hw_rotator_present_ && IsRotationRequired(hw_layers)) {
DLOGV_IF(kTagOfflineCtrl, "No Rotator device found");
return kErrorHardware;
}
error = CloseRotatorSession(hw_layers);
- if (LIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
DLOGE("Close rotator session failed for display %d", disp_offline_ctx->display_type);
return error;
}
@@ -101,13 +115,13 @@
if (IsRotationRequired(hw_layers)) {
error = OpenRotatorSession(hw_layers);
- if (LIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
DLOGE("Open rotator session failed for display %d", disp_offline_ctx->display_type);
return error;
}
- error = hw_intf_->Validate(hw_rotator_device_, hw_layers);
- if (LIKELY(error != kErrorNone)) {
+ error = hw_rotator_intf_->Validate(hw_layers);
+ if (error != kErrorNone) {
DLOGE("Rotator validation failed for display %d", disp_offline_ctx->display_type);
return error;
}
@@ -123,7 +137,7 @@
DisplayOfflineContext *disp_offline_ctx = reinterpret_cast<DisplayOfflineContext *>(display_ctx);
if (disp_offline_ctx->pending_rot_commit) {
- error = hw_intf_->Commit(hw_rotator_device_, hw_layers);
+ error = hw_rotator_intf_->Commit(hw_layers);
if (error != kErrorNone) {
DLOGE("Rotator commit failed for display %d", disp_offline_ctx->display_type);
return error;
@@ -153,8 +167,8 @@
rotate_info->input_buffer = layer.input_buffer;
rotate_info->frame_rate = layer.frame_rate;
- error = hw_intf_->OpenRotatorSession(hw_rotator_device_, rotate_info);
- if (LIKELY(error != kErrorNone)) {
+ error = hw_rotator_intf_->OpenSession(rotate_info);
+ if (error != kErrorNone) {
return error;
}
}
@@ -168,8 +182,8 @@
uint32_t i = 0;
while (hw_layers->closed_session_ids[i] >= 0) {
- error = hw_intf_->CloseRotatorSession(hw_rotator_device_, hw_layers->closed_session_ids[i]);
- if (LIKELY(error != kErrorNone)) {
+ error = hw_rotator_intf_->CloseSession(hw_layers->closed_session_ids[i]);
+ if (error != kErrorNone) {
return error;
}
hw_layers->closed_session_ids[i++] = -1;
diff --git a/displayengine/libs/core/offline_ctrl.h b/displayengine/libs/core/offline_ctrl.h
index fa8b264..1525bb8 100644
--- a/displayengine/libs/core/offline_ctrl.h
+++ b/displayengine/libs/core/offline_ctrl.h
@@ -27,15 +27,18 @@
#include <utils/locker.h>
#include <utils/debug.h>
-
-#include "hw_interface.h"
+#include <core/display_interface.h>
namespace sde {
+class HWRotatorInterface;
+class BufferSyncHandler;
+struct HWLayers;
+
class OfflineCtrl {
public:
OfflineCtrl();
- DisplayError Init(HWInterface *hw_intf, HWResourceInfo hw_res_info);
+ DisplayError Init(BufferSyncHandler *buffer_sync_handler);
DisplayError Deinit();
DisplayError RegisterDisplay(DisplayType type, Handle *display_ctx);
void UnregisterDisplay(Handle display_ctx);
@@ -54,8 +57,8 @@
DisplayError CloseRotatorSession(HWLayers *hw_layers);
bool IsRotationRequired(HWLayers *hw_layers);
- HWInterface *hw_intf_;
- Handle hw_rotator_device_;
+ HWRotatorInterface *hw_rotator_intf_;
+ bool hw_rotator_present_;
};
} // namespace sde
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index d5d3c58..ea90dfb 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -125,8 +125,8 @@
// 1. Source width is greater than split_left (left_mixer_width)
// 2. Pipe clock exceeds the mixer clock
if ((src_width > kMaxSourcePipeWidth) || (dst_width > kMaxSourcePipeWidth) ||
- (hw_res_info_.always_src_split && ((src_width > left_mixer_width) ||
- (pipe_clock > mixer_clock)))) {
+ (display_resource_ctx->display_attributes.always_src_split &&
+ ((src_width > left_mixer_width) || (pipe_clock > mixer_clock)))) {
SplitRect(transform.flip_horizontal, src_rect, dst_rect, &left_pipe->src_roi,
&left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi, align_x);
left_pipe->valid = true;
@@ -644,7 +644,7 @@
return error;
}
-DisplayError ResManager::CalculateDecimation(float downscale, uint8_t* decimation) {
+DisplayError ResManager::CalculateDecimation(float downscale, uint8_t *decimation) {
float max_down_scale = FLOAT(hw_res_info_.max_scale_down);
if (downscale <= max_down_scale) {
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index 3287224..7f78b29 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -26,6 +26,7 @@
#define __RES_MANAGER_H__
#include <core/display_interface.h>
+#include <private/hw_info_types.h>
#include <utils/locker.h>
#include "hw_interface.h"
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/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 1d0a40a..4f342db 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2015, 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
@@ -143,6 +143,9 @@
case HAL_PIXEL_FORMAT_RAW_SENSOR:
aligned_w = ALIGN(width, 32);
break;
+ case HAL_PIXEL_FORMAT_RAW10:
+ aligned_w = ALIGN(width * 10 /8, 16);
+ break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
aligned_w = ALIGN(width, 128);
break;
@@ -451,6 +454,9 @@
case HAL_PIXEL_FORMAT_RAW_SENSOR:
size = alignedw * alignedh * 2;
break;
+ case HAL_PIXEL_FORMAT_RAW10:
+ size = ALIGN(alignedw * alignedh, 4096);
+ break;
// adreno formats
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: // NV21
@@ -656,6 +662,7 @@
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
case HAL_PIXEL_FORMAT_NV21_ZSL:
case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW10:
ystride = cstride = width;
ycbcr->y = (void*)hnd->base;
ycbcr->cr = (void*)(hnd->base + ystride * height);
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 3026d99..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
@@ -222,6 +224,7 @@
ctx->mLayerRotMap[i]->reset();
}
+ memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
ctx->mAD->reset();
}
@@ -277,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 &&
@@ -530,7 +534,7 @@
}
break;
case HWC_DISPLAY_EXTERNAL:
- if(mode == HWC_POWER_MODE_OFF) {
+ if(mode == HWC_POWER_MODE_OFF and ctx->dpyAttr[dpy].connected) {
if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
ALOGE("%s: displayCommit failed for external", __FUNCTION__);
ret = -1;
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 7244562..5a9caec 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -453,6 +453,7 @@
if(hnd && fbhnd && (hnd->size == fbhnd->size) &&
(hnd->width == fbhnd->width) && (hnd->height == fbhnd->height)){
if(tmpLayer->transform ||
+ (list->flags & HWC_GEOMETRY_CHANGED) ||
(!(hnd->format == HAL_PIXEL_FORMAT_RGBA_8888 ||
hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)) ||
(needsScaling(tmpLayer) == true)) {
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index fb69fdd..5572cc4 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -461,6 +461,13 @@
if(mdpHw.hasMinCropWidthLimitation() and (crop_w < 5 or crop_h < 5))
return false;
+ /* crop_w and crop_h should be even for yuv layer, so fallback to GPU for
+ * those cases
+ */
+ if(isYuvBuffer(hnd) && (crop_w < 2 || crop_h < 2)) {
+ return false;
+ }
+
if((w_scale > 1.0f) || (h_scale > 1.0f)) {
const uint32_t maxMDPDownscale = mdpHw.getMaxMDPDownscale();
const float w_dscale = w_scale;
@@ -525,6 +532,14 @@
ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
__FUNCTION__);
ret = false;
+ } else if((qdutils::MDPVersion::getInstance().is8x26() ||
+ qdutils::MDPVersion::getInstance().is8x16() ||
+ qdutils::MDPVersion::getInstance().is8x39()) &&
+ !mDpy && isSecondaryAnimating(ctx) &&
+ isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) {
+ ALOGD_IF(isDebug(),"%s: Display animation in progress",
+ __FUNCTION__);
+ ret = false;
} else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
/* TODO: freeing up all the resources only for the targets having total
number of pipes < 8. Need to analyze number of VIG pipes used
@@ -818,6 +833,14 @@
return false;
}
+ if(!mDpy && isSecondaryAnimating(ctx) &&
+ (isYuvPresent(ctx,HWC_DISPLAY_EXTERNAL) ||
+ isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) ) {
+ ALOGD_IF(isDebug(),"%s: Display animation in progress",
+ __FUNCTION__);
+ return false;
+ }
+
// if secondary is configuring or Padding round, fall back to video only
// composition and release all assigned non VIG pipes from primary.
if(isSecondaryConfiguring(ctx)) {
@@ -2024,9 +2047,6 @@
}
}
}
- // reset PTOR
- if(!mDpy)
- memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
//reset old data
mCurrentFrame.reset(numLayers);
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 27243c4..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;
@@ -2700,32 +2709,18 @@
void processBootAnimCompleted(hwc_context_t *ctx) {
char value[PROPERTY_VALUE_MAX];
- int boot_finished = 0, ret = -1;
- int (*applyMode)(int) = NULL;
- void *modeHandle = NULL;
+ int ret = -1;
- // Reading property set on boot finish in SF
- property_get("service.bootanim.exit", value, "0");
- boot_finished = atoi(value);
- if (!boot_finished)
- return;
+ // Applying default mode after bootanimation is finished
+ property_get("init.svc.bootanim", value, "running");
- 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__);
+ if (!strncmp(value,"stopped",strlen("stopped"))) {
+ ctx->mBootAnimCompleted = true;
+
+ //one-shot action check if bootanimation completed then apply
+ //default display mode.
+ qdcmApplyDefaultAfterBootAnimationDone(ctx);
}
-
- ctx->mBootAnimCompleted = true;
}
void BwcPM::setBwc(const hwc_context_t *ctx, const int& dpy,
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index f290dc8..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 {
@@ -728,6 +741,16 @@
ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected);
}
+static inline bool isSecondaryAnimating(hwc_context_t* ctx) {
+ return (ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected &&
+ (!ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isPause) &&
+ ctx->listStats[HWC_DISPLAY_EXTERNAL].isDisplayAnimating)
+ ||
+ (ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected &&
+ (!ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause) &&
+ ctx->listStats[HWC_DISPLAY_VIRTUAL].isDisplayAnimating);
+}
+
/* Return Virtual Display connection status */
static inline bool isVDConnected(hwc_context_t* ctx) {
return ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected;
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 0c31dd3..828f4fc 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -175,12 +175,15 @@
mOVInfo.src_rect.w = utils::aligndown(mOVInfo.src_rect.w, 4);
}
} else {
+ // On 8974 and 8x26, there is a limitation of 1-pixel down-scaling
if (mdpVersion >= MDSS_V5) {
- // Check for 1-pixel down-scaling
- if (mOVInfo.src_rect.w - mOVInfo.dst_rect.w == 1)
- mOVInfo.src_rect.w -= 1;
- if (mOVInfo.src_rect.h - mOVInfo.dst_rect.h == 1)
- mOVInfo.src_rect.h -= 1;
+ if(qdutils::MDPVersion::getInstance().is8x74v2() ||
+ qdutils::MDPVersion::getInstance().is8x26()) {
+ if (mOVInfo.src_rect.w - mOVInfo.dst_rect.w == 1)
+ mOVInfo.src_rect.w -= 1;
+ if (mOVInfo.src_rect.h - mOVInfo.dst_rect.h == 1)
+ mOVInfo.src_rect.h -= 1;
+ }
}
}
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index e045918..a6a1b85 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -256,6 +256,7 @@
ALOGI("PartialUpdate disabled by property");
}
fclose(panelInfoNodeFP);
+ free(readLine);
} else {
ALOGE("Failed to open msm_fb_panel_info node");
}
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