summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRamkumar Radhakrishnan <ramkumar@codeaurora.org>2018-08-08 13:55:08 -0700
committerRamkumar Radhakrishnan <ramkumar@codeaurora.org>2018-08-21 14:37:31 -0700
commit7ef1a992b71b63d34c84a9a3aea6727e7923232d (patch)
tree74735b3ed597e8194992a0bfc4031320be13c5af
parent9ec9547d998cd5f4af4226593930bba53d8c66e1 (diff)
downloadandroid_hardware_qcom_sdm710_display-7ef1a992b71b63d34c84a9a3aea6727e7923232d.tar.gz
android_hardware_qcom_sdm710_display-7ef1a992b71b63d34c84a9a3aea6727e7923232d.tar.bz2
android_hardware_qcom_sdm710_display-7ef1a992b71b63d34c84a9a3aea6727e7923232d.zip
sdm: Define client interface to enable/disable idle pc
1. Define client interface to enable/disable idle power collapse 2. Maintain refcount to handle concurrent enable/disable 3. Trigger the screen refresh and wait for the next frame commit done event before returning the control to the client on disable idle pc 4. Enable idle pc on suspend and reset the refcount 5. Add binder support to enable/disable idle pc CRs-Fixed: 2255316 Change-Id:Ibcaf9d4edca502cc91e9b201be822bd48313a635
-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.cpp11
-rw-r--r--sdm/libs/hwc2/hwc_display_primary.h1
-rw-r--r--sdm/libs/hwc2/hwc_session.cpp59
-rw-r--r--sdm/libs/hwc2/hwc_session.h26
-rw-r--r--sdm/libs/hwc2/hwc_session_services.cpp49
25 files changed, 292 insertions, 27 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 56b612f6..9653fa82 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -771,4 +771,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 596bb983..40f0f489 100644
--- a/sdm/libs/hwc2/hwc_display_primary.h
+++ b/sdm/libs/hwc2/hwc_display_primary.h
@@ -78,6 +78,7 @@ class HWCDisplayPrimary : public HWCDisplay {
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,
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 6520c3ee..aa2c22c7 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -842,7 +842,17 @@ int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display,
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 +1332,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;
@@ -2012,14 +2030,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 +2129,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..8f4c7c20 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;
@@ -174,7 +182,7 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli
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 +240,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 +272,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 +299,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