diff options
author | Cyan_Hsieh <cyanhsieh@google.com> | 2018-09-25 11:13:52 +0800 |
---|---|---|
committer | Cyan_Hsieh <cyanhsieh@google.com> | 2018-09-25 11:20:21 +0800 |
commit | ad0413cad4b4adbec1ae30b0ee5eaf50d0004d72 (patch) | |
tree | ee96edd99990b24839c6743d8c8103bbf9f82f69 | |
parent | ca890cb965fb73b217cf0f269880944e7572eff4 (diff) | |
parent | 0d0d8fb1dbac70212796bc3e4a93d3b936ac5101 (diff) | |
download | android_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
25 files changed, 432 insertions, 35 deletions
@@ -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 |