summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCyan_Hsieh <cyanhsieh@google.com>2018-09-25 11:13:52 +0800
committerCyan_Hsieh <cyanhsieh@google.com>2018-09-25 11:20:21 +0800
commitad0413cad4b4adbec1ae30b0ee5eaf50d0004d72 (patch)
treeee96edd99990b24839c6743d8c8103bbf9f82f69
parentca890cb965fb73b217cf0f269880944e7572eff4 (diff)
parent0d0d8fb1dbac70212796bc3e4a93d3b936ac5101 (diff)
downloadandroid_hardware_qcom_sdm710_display-ad0413cad4b4adbec1ae30b0ee5eaf50d0004d72.tar.gz
android_hardware_qcom_sdm710_display-ad0413cad4b4adbec1ae30b0ee5eaf50d0004d72.tar.bz2
android_hardware_qcom_sdm710_display-ad0413cad4b4adbec1ae30b0ee5eaf50d0004d72.zip
Merge remote-tracking branch 'goog/qcom/release/LA.UM.7.8.9.08.00.00.478.078' into pi-dev
Bug: 116473492 Change-Id: I57b01175e9300fad89683201bfb7dd271c58fd05
-rw-r--r--common.mk15
-rw-r--r--libdrmutils/drm_interface.h13
-rw-r--r--libqservice/IQService.h1
-rw-r--r--sdm/include/core/display_interface.h9
-rw-r--r--sdm/libs/core/display_base.h3
-rw-r--r--sdm/libs/core/display_primary.cpp13
-rw-r--r--sdm/libs/core/display_primary.h1
-rw-r--r--sdm/libs/core/drm/hw_device_drm.cpp12
-rw-r--r--sdm/libs/core/drm/hw_device_drm.h5
-rw-r--r--sdm/libs/core/drm/hw_peripheral_drm.cpp42
-rw-r--r--sdm/libs/core/drm/hw_peripheral_drm.h8
-rw-r--r--sdm/libs/core/drm/hw_tv_drm.cpp14
-rw-r--r--sdm/libs/core/drm/hw_tv_drm.h1
-rw-r--r--sdm/libs/core/drm/hw_virtual_drm.cpp19
-rw-r--r--sdm/libs/core/drm/hw_virtual_drm.h1
-rw-r--r--sdm/libs/core/fb/hw_device.h3
-rw-r--r--sdm/libs/core/hw_interface.h1
-rw-r--r--sdm/libs/hwc2/Android.mk8
-rw-r--r--sdm/libs/hwc2/display_null.h1
-rw-r--r--sdm/libs/hwc2/hwc_display.h3
-rw-r--r--sdm/libs/hwc2/hwc_display_primary.cpp96
-rw-r--r--sdm/libs/hwc2/hwc_display_primary.h18
-rw-r--r--sdm/libs/hwc2/hwc_session.cpp103
-rw-r--r--sdm/libs/hwc2/hwc_session.h28
-rw-r--r--sdm/libs/hwc2/hwc_session_services.cpp49
25 files changed, 432 insertions, 35 deletions
diff --git a/common.mk b/common.mk
index 77658c0a..23c9529b 100644
--- a/common.mk
+++ b/common.mk
@@ -1,5 +1,14 @@
#Common headers
display_top := $(call my-dir)
+display_config_version := $(shell \
+ if [ -d "$(TOP)/vendor/qcom/opensource/interfaces/display/config/1.1" ];\
+ then echo DISPLAY_CONFIG_1_1; fi)
+display_config_version := $(shell \
+ if [ -d "$(TOP)/vendor/qcom/opensource/interfaces/display/config/1.2" ];\
+ then echo DISPLAY_CONFIG_1_2; fi)
+display_config_version := $(shell \
+ if [ -d "$(TOP)/vendor/qcom/opensource/interfaces/display/config/1.3" ];\
+ then echo DISPLAY_CONFIG_1_3; fi)
#Common C flags
common_flags := -Wno-missing-field-initializers
@@ -13,6 +22,12 @@ endif
ifeq ($(display_config_version), DISPLAY_CONFIG_1_1)
common_flags += -DDISPLAY_CONFIG_1_1
endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_2)
+ common_flags += -DDISPLAY_CONFIG_1_2 -DDISPLAY_CONFIG_1_1
+endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_3)
+ common_flags += -DDISPLAY_CONFIG_1_1 -DDISPLAY_CONFIG_1_2 -DDISPLAY_CONFIG_1_3
+endif
ifeq ($(TARGET_USES_COLOR_METADATA), true)
common_flags += -DUSE_COLOR_METADATA
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 94eb6899..c504c2c8 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -279,6 +279,12 @@ enum struct DRMOps {
*/
CRTC_SET_CAPTURE_MODE,
/*
+ * Op: Sets Idle PC state for CRTC.
+ * Arg: uint32_t - CRTC ID
+ * uint32_t - idle pc state
+ */
+ CRTC_SET_IDLE_PC_STATE,
+ /*
* Op: Returns retire fence for this commit. Should be called after Commit() on
* DRMAtomicReqInterface.
* Arg: uint32_t - Connector ID
@@ -367,6 +373,13 @@ enum struct DRMSrcConfig {
DEINTERLACE = 0,
};
+enum struct DRMIdlePCState {
+ NONE,
+ ENABLE,
+ DISABLE,
+};
+
+
/* Display type to identify a suitable connector */
enum struct DRMDisplayType {
PERIPHERAL,
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 7d02fac9..b2012560 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -78,6 +78,7 @@ public:
SET_COLOR_MODE_BY_ID = 36, // Overrides the QDCM mode using the given mode ID
GET_COMPOSER_STATUS = 37, // Get composer init status-true if primary display init is done
SET_COLOR_MODE_WITH_RENDER_INTENT = 38,
+ SET_IDLE_PC = 39, // Enable/disable Idle power collapse
COMMAND_LIST_END = 400,
};
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 70f6e80a..8b724da1 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -685,6 +685,15 @@ class DisplayInterface {
LayerBufferFormat format,
const ColorMetaData &color_metadata) = 0;
+ /*! @brief Method to control idle power collapse feature for primary display.
+
+ @param[in] enable idle power collapse feature control flag
+ @param[in] synchronous commit flag
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) = 0;
+
/*
* Returns a string consisting of a dump of SDM's display and layer related state
* as programmed to driver
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index fcc076cd..d5c32a96 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -116,6 +116,9 @@ class DisplayBase : public DisplayInterface {
LayerBufferFormat format,
const ColorMetaData &color_metadata);
virtual std::string Dump();
+ virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) {
+ return kErrorNotSupported;
+ }
protected:
DisplayError BuildLayerStackStats(LayerStack *layer_stack);
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index ba83d05c..4326d8ea 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -416,5 +416,18 @@ void DisplayPrimary::ResetPanel() {
}
}
+DisplayError DisplayPrimary::ControlIdlePowerCollapse(bool enable, bool synchronous) {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (!active_) {
+ DLOGW("Invalid display state = %d. Panel must be on.", state_);
+ return kErrorPermission;
+ }
+ if (hw_panel_info_.mode == kModeVideo) {
+ DLOGW("Idle power collapse not supported for video mode panel.");
+ return kErrorNotSupported;
+ }
+ return hw_intf_->ControlIdlePowerCollapse(enable, synchronous);
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index a5a3ae0f..60dee5c7 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -51,6 +51,7 @@ class DisplayPrimary : public DisplayBase, HWEventHandler {
virtual DisplayError SetRefreshRate(uint32_t refresh_rate, bool final_rate);
virtual DisplayError SetPanelBrightness(int level);
virtual DisplayError GetPanelBrightness(int *level);
+ virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous);
// Implement the HWEventHandlers
virtual DisplayError VSync(int64_t timestamp);
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index aee7cae3..627e0080 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -755,16 +755,6 @@ DisplayError HWDeviceDRM::GetConfigIndex(char *mode, uint32_t *index) {
}
DisplayError HWDeviceDRM::PowerOn(int *release_fence) {
- DTRACE_SCOPED();
- if (!drm_atomic_intf_) {
- DLOGE("DRM Atomic Interface is null!");
- return kErrorUndefined;
- }
-
- if (first_cycle_) {
- return kErrorNone;
- }
-
update_mode_ = true;
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::ON);
@@ -1143,7 +1133,7 @@ DisplayError HWDeviceDRM::AtomicCommit(HWLayers *hw_layers) {
DTRACE_SCOPED();
SetupAtomic(hw_layers, false /* validate */);
- int ret = drm_atomic_intf_->Commit(false /* synchronous */, false /* retain_planes*/);
+ int ret = drm_atomic_intf_->Commit(synchronous_commit_, false /* retain_planes*/);
if (ret) {
DLOGE("%s failed with error %d crtc %d", __FUNCTION__, ret, token_.crtc_id);
vrefresh_ = 0;
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 9caa0955..63853c4a 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -101,6 +101,9 @@ class HWDeviceDRM : public HWInterface {
virtual void InitializeConfigs();
virtual DisplayError DumpDebugData() { return kErrorNone; }
virtual void PopulateHWPanelInfo();
+ virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) {
+ return kErrorNotSupported;
+ }
enum {
kHWEventVSync,
@@ -182,9 +185,9 @@ class HWDeviceDRM : public HWInterface {
uint32_t current_mode_index_ = 0;
sde_drm::DRMConnectorInfo connector_info_ = {};
bool first_cycle_ = true;
+ bool synchronous_commit_ = false;
private:
- bool synchronous_commit_ = false;
HWMixerAttributes mixer_attributes_ = {};
std::string interface_str_ = "DSI";
std::vector<sde_drm::DRMSolidfillStage> solid_fills_ {};
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
index 87c99495..03403e5a 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.cpp
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -66,6 +66,7 @@ DisplayError HWPeripheralDRM::Validate(HWLayers *hw_layers) {
HWLayersInfo &hw_layer_info = hw_layers->info;
SetDestScalarData(hw_layer_info);
SetupConcurrentWriteback(hw_layer_info, true);
+ SetIdlePCState();
return HWDeviceDRM::Validate(hw_layers);
}
@@ -74,13 +75,20 @@ DisplayError HWPeripheralDRM::Commit(HWLayers *hw_layers) {
HWLayersInfo &hw_layer_info = hw_layers->info;
SetDestScalarData(hw_layer_info);
SetupConcurrentWriteback(hw_layer_info, false);
+ SetIdlePCState();
DisplayError error = HWDeviceDRM::Commit(hw_layers);
+ if (error != kErrorNone) {
+ return error;
+ }
if (cwb_config_.enabled && (error == kErrorNone)) {
PostCommitConcurrentWriteback(hw_layer_info.stack->output_buffer);
}
+ // Initialize to default after successful commit
+ synchronous_commit_ = false;
+
return error;
}
@@ -241,4 +249,38 @@ void HWPeripheralDRM::PostCommitConcurrentWriteback(LayerBuffer *output_buffer)
}
}
+DisplayError HWPeripheralDRM::ControlIdlePowerCollapse(bool enable, bool synchronous) {
+ sde_drm::DRMIdlePCState idle_pc_state =
+ enable ? sde_drm::DRMIdlePCState::ENABLE : sde_drm::DRMIdlePCState::DISABLE;
+ if (idle_pc_state == idle_pc_state_) {
+ return kErrorNone;
+ }
+ // As idle PC is disabled after subsequent commit, Make sure to have synchrounous commit and
+ // ensure TA accesses the display_cc registers after idle PC is disabled.
+ idle_pc_state_ = idle_pc_state;
+ synchronous_commit_ = !enable ? synchronous : false;
+ return kErrorNone;
+}
+
+DisplayError HWPeripheralDRM::PowerOn(int *release_fence) {
+ DTRACE_SCOPED();
+ if (!drm_atomic_intf_) {
+ DLOGE("DRM Atomic Interface is null!");
+ return kErrorUndefined;
+ }
+
+ if (first_cycle_) {
+ return kErrorNone;
+ }
+ drm_atomic_intf_->Perform(sde_drm::DRMOps::CRTC_SET_IDLE_PC_STATE, token_.crtc_id,
+ sde_drm::DRMIdlePCState::ENABLE);
+ DisplayError err = HWDeviceDRM::PowerOn(release_fence);
+ if (err != kErrorNone) {
+ return err;
+ }
+ idle_pc_state_ = sde_drm::DRMIdlePCState::ENABLE;
+
+ return kErrorNone;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.h b/sdm/libs/core/drm/hw_peripheral_drm.h
index b3b8306c..365da42c 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.h
+++ b/sdm/libs/core/drm/hw_peripheral_drm.h
@@ -52,6 +52,9 @@ class HWPeripheralDRM : public HWDeviceDRM {
virtual DisplayError Validate(HWLayers *hw_layers);
virtual DisplayError Commit(HWLayers *hw_layers);
virtual DisplayError Flush();
+ virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous);
+ virtual DisplayError PowerOn(int *release_fence);
+
private:
void SetDestScalarData(HWLayersInfo hw_layer_info);
void ResetDisplayParams();
@@ -59,10 +62,15 @@ class HWPeripheralDRM : public HWDeviceDRM {
void SetupConcurrentWriteback(const HWLayersInfo &hw_layer_info, bool validate);
void ConfigureConcurrentWriteback(LayerStack *stack);
void PostCommitConcurrentWriteback(LayerBuffer *output_buffer);
+ void SetIdlePCState() {
+ drm_atomic_intf_->Perform(sde_drm::DRMOps::CRTC_SET_IDLE_PC_STATE, token_.crtc_id,
+ idle_pc_state_);
+ }
sde_drm_dest_scaler_data sde_dest_scalar_data_ = {};
std::vector<SDEScaler> scalar_data_ = {};
CWBConfig cwb_config_ = {};
+ sde_drm::DRMIdlePCState idle_pc_state_ = sde_drm::DRMIdlePCState::NONE;
};
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index adf1f1ea..8e141e32 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -317,5 +317,19 @@ DisplayError HWTVDRM::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
return error;
}
+DisplayError HWTVDRM::PowerOn(int *release_fence) {
+ DTRACE_SCOPED();
+ if (!drm_atomic_intf_) {
+ DLOGE("DRM Atomic Interface is null!");
+ return kErrorUndefined;
+ }
+
+ if (first_cycle_) {
+ return kErrorNone;
+ }
+
+ return HWDeviceDRM::PowerOn(release_fence);
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_tv_drm.h b/sdm/libs/core/drm/hw_tv_drm.h
index 3e592f97..93d4e73f 100644
--- a/sdm/libs/core/drm/hw_tv_drm.h
+++ b/sdm/libs/core/drm/hw_tv_drm.h
@@ -49,6 +49,7 @@ class HWTVDRM : public HWDeviceDRM {
virtual DisplayError Commit(HWLayers *hw_layers);
virtual void PopulateHWPanelInfo();
virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
+ virtual DisplayError PowerOn(int *release_fence);
private:
DisplayError UpdateHDRMetaData(HWLayers *hw_layers);
diff --git a/sdm/libs/core/drm/hw_virtual_drm.cpp b/sdm/libs/core/drm/hw_virtual_drm.cpp
index a2e84a29..16afe489 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.cpp
+++ b/sdm/libs/core/drm/hw_virtual_drm.cpp
@@ -207,5 +207,24 @@ void HWVirtualDRM::GetModeIndex(const HWDisplayAttributes &display_attributes, i
}
}
+DisplayError HWVirtualDRM::PowerOn(int *release_fence) {
+ DTRACE_SCOPED();
+ if (!drm_atomic_intf_) {
+ DLOGE("DRM Atomic Interface is null!");
+ return kErrorUndefined;
+ }
+
+ if (first_cycle_) {
+ return kErrorNone;
+ }
+
+ DisplayError err = HWDeviceDRM::PowerOn(release_fence);
+ if (err != kErrorNone) {
+ return err;
+ }
+
+ return kErrorNone;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_virtual_drm.h b/sdm/libs/core/drm/hw_virtual_drm.h
index d89737e3..392b9bf5 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.h
+++ b/sdm/libs/core/drm/hw_virtual_drm.h
@@ -52,6 +52,7 @@ class HWVirtualDRM : public HWDeviceDRM {
virtual DisplayError Validate(HWLayers *hw_layers);
virtual DisplayError Commit(HWLayers *hw_layers);
virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
+ virtual DisplayError PowerOn(int *release_fence);
private:
void ConfigureWbConnectorFbId(uint32_t fb_id);
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index fe954aee..636baa5b 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -97,6 +97,9 @@ class HWDevice : public HWInterface {
virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
virtual DisplayError DumpDebugData();
+ virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) {
+ return kErrorNotSupported;
+ }
enum {
kHWEventVSync,
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index cdb7cbad..143391c2 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -112,6 +112,7 @@ class HWInterface {
virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) = 0;
virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes) = 0;
virtual DisplayError DumpDebugData() = 0;
+ virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) = 0;
protected:
virtual ~HWInterface() { }
diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk
index a671c31b..8d02197b 100644
--- a/sdm/libs/hwc2/Android.mk
+++ b/sdm/libs/hwc2/Android.mk
@@ -29,6 +29,14 @@ LOCAL_SHARED_LIBRARIES := libsdmcore libqservice libbinder libhardware li
ifeq ($(display_config_version), DISPLAY_CONFIG_1_1)
LOCAL_SHARED_LIBRARIES += vendor.display.config@1.1
endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_2)
+LOCAL_SHARED_LIBRARIES += vendor.display.config@1.2 vendor.display.config@1.1
+endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_3)
+LOCAL_SHARED_LIBRARIES += vendor.display.config@1.1
+LOCAL_SHARED_LIBRARIES += vendor.display.config@1.2
+LOCAL_SHARED_LIBRARIES += vendor.display.config@1.3
+endif
LOCAL_SRC_FILES := hwc_session.cpp \
hwc_session_services.cpp \
diff --git a/sdm/libs/hwc2/display_null.h b/sdm/libs/hwc2/display_null.h
index bd49a162..dbfc7199 100644
--- a/sdm/libs/hwc2/display_null.h
+++ b/sdm/libs/hwc2/display_null.h
@@ -97,6 +97,7 @@ class DisplayNull : public DisplayInterface {
MAKE_NO_OP(SetCompositionState(LayerComposition, bool))
MAKE_NO_OP(GetClientTargetSupport(uint32_t, uint32_t, LayerBufferFormat,
const ColorMetaData &))
+ MAKE_NO_OP(ControlIdlePowerCollapse(bool, bool))
std::string Dump() { return ""; }
private:
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 5dfe3c01..49406785 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -255,6 +255,9 @@ class HWCDisplay : public DisplayEventHandler {
return HWC2::Error::None;
}
virtual HWC2::Error GetValidateDisplayOutput(uint32_t *out_num_types, uint32_t *out_num_requests);
+ virtual HWC2::Error ControlIdlePowerCollapse(bool enable, bool synchronous) {
+ return HWC2::Error::Unsupported;
+ }
protected:
// Maximum number of layers supported by display manager.
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp
index f86fbe1d..1a6944b2 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -46,6 +46,50 @@
namespace sdm {
+DisplayError HWCDisplayPrimary::PMICInterface::Init() {
+ std::string str_lcd_bias("/sys/class/lcd_bias/secure_mode");
+ fd_lcd_bias_ = ::open(str_lcd_bias.c_str(), O_WRONLY);
+ if (fd_lcd_bias_ < 0) {
+ DLOGE("File '%s' could not be opened. errno = %d, desc = %s", str_lcd_bias.c_str(), errno,
+ strerror(errno));
+ return kErrorHardware;
+ }
+
+ std::string str_leds_wled("/sys/class/leds/wled/secure_mode");
+ fd_wled_ = ::open(str_leds_wled.c_str(), O_WRONLY);
+ if (fd_wled_ < 0) {
+ DLOGE("File '%s' could not be opened. errno = %d, desc = %s", str_leds_wled.c_str(), errno,
+ strerror(errno));
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+void HWCDisplayPrimary::PMICInterface::Deinit() {
+ ::close(fd_lcd_bias_);
+ ::close(fd_wled_);
+}
+
+DisplayError HWCDisplayPrimary::PMICInterface::Notify(bool secure_display_start) {
+ std::string str_sd_start = secure_display_start ? std::to_string(1) : std::to_string(0);
+ ssize_t err = ::pwrite(fd_lcd_bias_, str_sd_start.c_str(), str_sd_start.length(), 0);
+ if (err <= 0) {
+ DLOGE("Write failed for lcd_bias, Error = %s", strerror(errno));
+ return kErrorHardware;
+ }
+
+ err = ::pwrite(fd_wled_, str_sd_start.c_str(), str_sd_start.length(), 0);
+ if (err <= 0) {
+ DLOGE("Write failed for wled, Error = %s", strerror(errno));
+ return kErrorHardware;
+ }
+
+ DLOGI("Successfully notifed about secure display %s to PMIC driver",
+ secure_display_start ? "start": "end");
+ return kErrorNone;
+}
+
int HWCDisplayPrimary::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, qService::QService *qservice,
HWCDisplay **hwc_display) {
@@ -116,9 +160,23 @@ int HWCDisplayPrimary::Init() {
color_mode_->Init();
HWCDebugHandler::Get()->GetProperty(ENABLE_DEFAULT_COLOR_MODE, &default_mode_status_);
+ pmic_intf_ = new PMICInterface();
+ pmic_intf_->Init();
+
return status;
}
+int HWCDisplayPrimary::Deinit() {
+ int status = HWCDisplay::Deinit();
+ if (status) {
+ return status;
+ }
+ pmic_intf_->Deinit();
+ delete pmic_intf_;
+
+ return 0;
+}
+
void HWCDisplayPrimary::ProcessBootAnimCompleted() {
uint32_t numBootUpLayers = 0;
// TODO(user): Remove this hack
@@ -247,7 +305,7 @@ HWC2::Error HWCDisplayPrimary::Present(int32_t *out_retire_fence) {
if (status == HWC2::Error::None) {
HandleFrameOutput();
SolidFillCommit();
- status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
+ status = PostCommitLayerStack(out_retire_fence);
}
}
@@ -386,6 +444,26 @@ HWC2::Error HWCDisplayPrimary::GetReadbackBufferFence(int32_t *release_fence) {
return status;
}
+HWC2::Error HWCDisplayPrimary::PostCommitLayerStack(int32_t *out_retire_fence) {
+ auto status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
+ if (status != HWC2::Error::None) {
+ return status;
+ }
+
+ if (pmic_notification_pending_) {
+ // Wait for current commit to complete
+ if (*out_retire_fence >= 0) {
+ int ret = sync_wait(*out_retire_fence, 1000);
+ if (ret < 0) {
+ DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ }
+ }
+ pmic_intf_->Notify(false /* secure_display_start */);
+ pmic_notification_pending_ = false;
+ }
+ return HWC2::Error::None;
+}
+
int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
va_list args;
va_start(args, operation);
@@ -472,6 +550,11 @@ void HWCDisplayPrimary::SetSecureDisplay(bool secure_display_active) {
DLOGI("SecureDisplay state changed from %d to %d Needs Flush!!", secure_display_active_,
secure_display_active);
secure_display_active_ = secure_display_active;
+ if (secure_display_active_) {
+ pmic_intf_->Notify(true /* secure_display_start */);
+ } else {
+ pmic_notification_pending_ = true;
+ }
// Avoid flush for Command mode panel.
DisplayConfigFixedInfo display_config;
@@ -693,4 +776,15 @@ DisplayError HWCDisplayPrimary::GetMixerResolution(uint32_t *width, uint32_t *he
return display_intf_->GetMixerResolution(width, height);
}
+HWC2::Error HWCDisplayPrimary::ControlIdlePowerCollapse(bool enable, bool synchronous) {
+ DisplayError error = kErrorNone;
+
+ if (display_intf_) {
+ error = display_intf_->ControlIdlePowerCollapse(enable, synchronous);
+ validated_ = false;
+ }
+
+ return (error != kErrorNone) ? HWC2::Error::Unsupported : HWC2::Error::None;
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display_primary.h b/sdm/libs/hwc2/hwc_display_primary.h
index 7f5e50c9..40f0f489 100644
--- a/sdm/libs/hwc2/hwc_display_primary.h
+++ b/sdm/libs/hwc2/hwc_display_primary.h
@@ -53,6 +53,7 @@ class HWCDisplayPrimary : public HWCDisplay {
HWCDisplay **hwc_display);
static void Destroy(HWCDisplay *hwc_display);
virtual int Init();
+ virtual int Deinit();
virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
virtual HWC2::Error Present(int32_t *out_retire_fence);
virtual HWC2::Error GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes);
@@ -76,6 +77,8 @@ class HWCDisplayPrimary : public HWCDisplay {
virtual HWC2::Error SetReadbackBuffer(const native_handle_t *buffer, int32_t acquire_fence,
bool post_processed_output);
virtual HWC2::Error GetReadbackBufferFence(int32_t *release_fence);
+ virtual HWC2::Error PostCommitLayerStack(int32_t *out_retire_fence);
+ virtual HWC2::Error ControlIdlePowerCollapse(bool enable, bool synchronous);
private:
HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
@@ -92,6 +95,18 @@ class HWCDisplayPrimary : public HWCDisplay {
void HandleFrameDump();
DisplayError SetMixerResolution(uint32_t width, uint32_t height);
DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+ class PMICInterface {
+ public:
+ PMICInterface() { }
+ ~PMICInterface() { }
+ DisplayError Init();
+ void Deinit();
+ DisplayError Notify(bool secure_display_start);
+
+ private:
+ int fd_lcd_bias_ = -1;
+ int fd_wled_ = -1;
+ };
BufferAllocator *buffer_allocator_ = nullptr;
CPUHint *cpu_hint_ = nullptr;
@@ -107,6 +122,9 @@ class HWCDisplayPrimary : public HWCDisplay {
BufferInfo output_buffer_info_ = {};
void *output_buffer_base_ = nullptr;
int default_mode_status_ = 0;
+ // PMIC interface to notify secure display start/end
+ PMICInterface *pmic_intf_ = nullptr;
+ bool pmic_notification_pending_ = false;
};
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 6520c3ee..e4404648 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -455,6 +455,11 @@ static int32_t GetRenderIntents(hwc2_device_t *device, hwc2_display_t display,
if (out_num_intents == nullptr) {
return HWC2_ERROR_BAD_PARAMETER;
}
+
+ if (mode < ColorMode::NATIVE || mode > ColorMode::BT2100_HLG) {
+ DLOGE("Invalid ColorMode: %d", mode);
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetRenderIntents, mode,
out_num_intents, out_intents);
}
@@ -557,12 +562,14 @@ static int32_t GetDisplayType(hwc2_device_t *device, hwc2_display_t display, int
return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayType, out_type);
}
-static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display, int32_t *out_support) {
+int32_t HWCSession::GetDozeSupport(hwc2_device_t *device, hwc2_display_t display,
+ int32_t *out_support) {
if (!device || !out_support) {
return HWC2_ERROR_BAD_PARAMETER;
}
- if (display >= HWC_NUM_DISPLAY_TYPES) {
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ if (display >= HWC_NUM_DISPLAY_TYPES || (hwc_session->hwc_display_[display] == nullptr) ) {
return HWC2_ERROR_BAD_DISPLAY;
}
@@ -606,7 +613,7 @@ int32_t HWCSession::PresentDisplay(hwc2_device_t *device, hwc2_display_t display
auto status = HWC2::Error::BadDisplay;
DTRACE_SCOPED();
- if (display >= HWC_NUM_DISPLAY_TYPES) {
+ if (display >= HWC_NUM_DISPLAY_TYPES || (hwc_session->hwc_display_[display] == nullptr)) {
return HWC2_ERROR_BAD_DISPLAY;
}
@@ -621,9 +628,7 @@ int32_t HWCSession::PresentDisplay(hwc2_device_t *device, hwc2_display_t display
}
// TODO(user): Handle virtual display/HDMI concurrency
- if (hwc_session->hwc_display_[display]) {
- status = hwc_session->PresentDisplayInternal(display, out_retire_fence);
- }
+ status = hwc_session->PresentDisplayInternal(display, out_retire_fence);
}
if (status != HWC2::Error::None && status != HWC2::Error::NotValidated) {
@@ -700,6 +705,11 @@ int32_t HWCSession::SetColorModeWithRenderIntent(hwc2_device_t *device, hwc2_dis
return HWC2_ERROR_BAD_PARAMETER;
}
auto render_intent = static_cast<RenderIntent>(int_render_intent);
+ if ((render_intent < RenderIntent::COLORIMETRIC) ||
+ (render_intent > RenderIntent::TONE_MAP_ENHANCE)) {
+ DLOGE("Invalid RenderIntent: %d", render_intent);
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorModeWithRenderIntent,
mode, render_intent);
}
@@ -837,12 +847,27 @@ int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display,
// all displays support on/off. Check for doze modes
int support = 0;
- GetDozeSupport(device, display, &support);
+
+ auto status = GetDozeSupport(device, display, &support);
+ if (status != HWC2_ERROR_NONE) {
+ return INT32(status);
+ }
+
if (!support && (mode == HWC2::PowerMode::Doze || mode == HWC2::PowerMode::DozeSuspend)) {
return HWC2_ERROR_UNSUPPORTED;
}
- return CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode);
+ auto error = CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode);
+ if (error != HWC2_ERROR_NONE) {
+ return error;
+ }
+ // Reset idle pc ref count on suspend, as we enable idle pc during suspend.
+ if (mode == HWC2::PowerMode::Off) {
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ hwc_session->idle_pc_ref_cnt_ = 0;
+ }
+
+ return HWC2_ERROR_NONE;
}
static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display, int32_t int_enabled) {
@@ -1322,6 +1347,14 @@ android::status_t HWCSession::notifyCallback(uint32_t command, const android::Pa
output_parcel->writeInt32(getComposerStatus());
break;
+ case qService::IQService::SET_IDLE_PC:
+ if (!input_parcel) {
+ DLOGE("QService command = %d: input_parcel needed.", command);
+ break;
+ }
+ status = SetIdlePC(input_parcel);
+ break;
+
default:
DLOGW("QService command = %d is not supported.", command);
break;
@@ -1506,6 +1539,11 @@ android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_
auto mode = static_cast<ColorMode>(input_parcel->readInt32());
auto device = static_cast<hwc2_device_t *>(this);
+ if (mode < ColorMode::NATIVE || mode > ColorMode::BT2100_HLG) {
+ DLOGE("Invalid ColorMode: %d", mode);
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
if (err != HWC2_ERROR_NONE)
return -EINVAL;
@@ -1520,6 +1558,16 @@ android::status_t HWCSession::SetColorModeWithRenderIntentOverride(
auto intent = static_cast<RenderIntent>(input_parcel->readInt32());
auto device = static_cast<hwc2_device_t *>(this);
+ if (mode < ColorMode::NATIVE || mode > ColorMode::BT2100_HLG) {
+ DLOGE("Invalid ColorMode: %d", mode);
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ if (intent < RenderIntent::COLORIMETRIC || intent > RenderIntent::TONE_MAP_ENHANCE) {
+ DLOGE("Invalid RenderIntent: %d", intent);
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
auto err =
CallDisplayFunction(device, display, &HWCDisplay::SetColorModeWithRenderIntent, mode, intent);
if (err != HWC2_ERROR_NONE)
@@ -2012,14 +2060,6 @@ int HWCSession::CreateExternalDisplay(int disp_id, uint32_t primary_width,
use_primary_res, &hwc_display_[disp_id]);
}
-#ifdef DISPLAY_CONFIG_1_1
-// Methods from ::vendor::hardware::display::config::V1_1::IDisplayConfig follow.
-Return<int32_t> HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) {
- return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
- &HWCDisplay::SetDisplayAnimating, animating);
-}
-#endif
-
HWC2::Error HWCSession::ValidateDisplayInternal(hwc2_display_t display, uint32_t *out_num_types,
uint32_t *out_num_requests) {
HWCDisplay *hwc_display = hwc_display_[display];
@@ -2119,4 +2159,35 @@ int32_t HWCSession::GetReadbackBufferFence(hwc2_device_t *device, hwc2_display_t
return CallDisplayFunction(device, display, &HWCDisplay::GetReadbackBufferFence, release_fence);
}
+android::status_t HWCSession::SetIdlePC(const android::Parcel *input_parcel) {
+ auto enable = input_parcel->readInt32();
+ auto synchronous = input_parcel->readInt32();
+
+#ifdef DISPLAY_CONFIG_1_3
+ return static_cast<android::status_t>(controlIdlePowerCollapse(enable, synchronous));
+#else
+ {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ DLOGE("Primary display is not ready");
+ return -EINVAL;
+ }
+ auto error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
+ if (error != HWC2::Error::None) {
+ return -EINVAL;
+ }
+ if (!enable) {
+ Refresh(HWC_DISPLAY_PRIMARY);
+ int32_t error = locker_[HWC_DISPLAY_PRIMARY].WaitFinite(kCommitDoneTimeoutMs);
+ if (error == ETIMEDOUT) {
+ DLOGE("Timed out!! Next frame commit done event not received!!");
+ return error;
+ }
+ }
+ DLOGI("Idle PC %s!!", enable ? "enabled" : "disabled");
+ }
+ return 0;
+#endif
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 725e9836..5b94b572 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -20,7 +20,11 @@
#ifndef __HWC_SESSION_H__
#define __HWC_SESSION_H__
-#ifdef DISPLAY_CONFIG_1_1
+#ifdef DISPLAY_CONFIG_1_3
+#include <vendor/display/config/1.3/IDisplayConfig.h>
+#elif DISPLAY_CONFIG_1_2
+#include <vendor/display/config/1.2/IDisplayConfig.h>
+#elif DISPLAY_CONFIG_1_1
#include <vendor/display/config/1.1/IDisplayConfig.h>
#else
#include <vendor/display/config/1.0/IDisplayConfig.h>
@@ -40,7 +44,11 @@
namespace sdm {
-#ifdef DISPLAY_CONFIG_1_1
+#ifdef DISPLAY_CONFIG_1_3
+using vendor::display::config::V1_3::IDisplayConfig;
+#elif DISPLAY_CONFIG_1_2
+using vendor::display::config::V1_2::IDisplayConfig;
+#elif DISPLAY_CONFIG_1_1
using vendor::display::config::V1_1::IDisplayConfig;
#else
using ::vendor::display::config::V1_0::IDisplayConfig;
@@ -169,12 +177,14 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli
const native_handle_t *buffer, int32_t acquire_fence);
static int32_t GetReadbackBufferFence(hwc2_device_t *device, hwc2_display_t display,
int32_t *release_fence);
+ static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display,
+ int32_t *out_support);
static Locker locker_[HWC_NUM_DISPLAY_TYPES];
private:
static const int kExternalConnectionTimeoutMs = 500;
- static const int kPartialUpdateControlTimeoutMs = 100;
+ static const int kCommitDoneTimeoutMs = 100;
// hwc methods
static int Open(const hw_module_t *module, const char *name, hw_device_t **device);
@@ -232,11 +242,17 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli
getHDRCapabilities_cb _hidl_cb) override;
Return<int32_t> setCameraLaunchStatus(uint32_t on) override;
Return<void> displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) override;
-
- // Methods from ::android::hardware::display::config::V1_1::IDisplayConfig follow.
#ifdef DISPLAY_CONFIG_1_1
Return<int32_t> setDisplayAnimating(uint64_t display_id, bool animating) override;
#endif
+ // Methods from ::android::hardware::display::config::V1_2::IDisplayConfig follow.
+#ifdef DISPLAY_CONFIG_1_2
+ Return<int32_t> setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type,
+ uint32_t base, uint32_t count) { return 0; }
+#endif
+#ifdef DISPLAY_CONFIG_1_3
+ Return<int32_t> controlIdlePowerCollapse(bool enable, bool synchronous) override;
+#endif
// QClient methods
virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
@@ -258,6 +274,7 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli
android::status_t SetColorModeById(const android::Parcel *input_parcel);
android::status_t getComposerStatus();
+ android::status_t SetIdlePC(const android::Parcel *input_parcel);
void Refresh(hwc2_display_t display);
void HotPlug(hwc2_display_t display, HWC2::Connection state);
@@ -284,6 +301,7 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli
Locker callbacks_lock_;
int hpd_bpp_ = 0;
int hpd_pattern_ = 0;
+ uint32_t idle_pc_ref_cnt_ = 0;
};
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 57a5dac1..519346f0 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -357,7 +357,7 @@ int32_t HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
Refresh(HWC_DISPLAY_PRIMARY);
// Wait until partial update control is complete
- int32_t error = locker_[disp_id].WaitFinite(kPartialUpdateControlTimeoutMs);
+ int32_t error = locker_[disp_id].WaitFinite(kCommitDoneTimeoutMs);
return error;
}
@@ -507,5 +507,52 @@ Return<void> HWCSession::displayBWTransactionPending(displayBWTransactionPending
return Void();
}
+#ifdef DISPLAY_CONFIG_1_1
+// Methods from ::vendor::hardware::display::config::V1_1::IDisplayConfig follow.
+Return<int32_t> HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) {
+ return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
+ &HWCDisplay::SetDisplayAnimating, animating);
+}
+#endif
+
+#ifdef DISPLAY_CONFIG_1_3
+Return<int32_t> HWCSession::controlIdlePowerCollapse(bool enable, bool synchronous) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ if (!enable) {
+ if (!idle_pc_ref_cnt_) {
+ HWC2::Error err =
+ hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
+ if (err != HWC2::Error::None) {
+ return -EINVAL;
+ }
+ Refresh(HWC_DISPLAY_PRIMARY);
+ int32_t error = locker_[HWC_DISPLAY_PRIMARY].WaitFinite(kCommitDoneTimeoutMs);
+ if (error == ETIMEDOUT) {
+ DLOGE("Timed out!! Next frame commit done event not received!!");
+ return error;
+ }
+ DLOGI("Idle PC disabled!!");
+ }
+ idle_pc_ref_cnt_++;
+ } else if (idle_pc_ref_cnt_ > 0) {
+ if (!(idle_pc_ref_cnt_ - 1)) {
+ HWC2::Error err =
+ hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
+ if (err != HWC2::Error::None) {
+ return -EINVAL;
+ }
+ DLOGI("Idle PC enabled!!");
+ }
+ idle_pc_ref_cnt_--;
+ }
+ return 0;
+ }
+
+ DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
+ return -ENODEV;
+}
+#endif // DISPLAY_CONFIG_1_3
} // namespace sdm