From 9ec9547d998cd5f4af4226593930bba53d8c66e1 Mon Sep 17 00:00:00 2001 From: Ramkumar Radhakrishnan Date: Wed, 25 Jul 2018 20:36:16 -0700 Subject: sdm: Notify secure display start/end to PMIC driver Notify secure display start/end to PMIC driver to disable PMIC irqs before the start of secure display session and enable PMIC irqs after the end of secure display session to avoid register access by PMIC drivers during secure display session. Change-Id: I6c71b7f0cb8c78be4144bd785b752c4e1ad0c86b CRs-Fixed: 2285937 --- sdm/libs/hwc2/hwc_display_primary.cpp | 80 ++++++++++++++++++++++++++++++++++- sdm/libs/hwc2/hwc_display_primary.h | 17 ++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) (limited to 'sdm') diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp index f86fbe1d..56b612f6 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,21 @@ HWC2::Error HWCDisplayPrimary::GetReadbackBufferFence(int32_t *release_fence) { return status; } +HWC2::Error HWCDisplayPrimary::PostCommitLayerStack(int32_t *out_retire_fence) { + 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 HWCDisplay::PostCommitLayerStack(out_retire_fence); +} + int HWCDisplayPrimary::Perform(uint32_t operation, ...) { va_list args; va_start(args, operation); @@ -472,6 +545,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; diff --git a/sdm/libs/hwc2/hwc_display_primary.h b/sdm/libs/hwc2/hwc_display_primary.h index 7f5e50c9..596bb983 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,7 @@ 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); private: HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator, @@ -92,6 +94,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 +121,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 -- cgit v1.2.3 From 045b22b208f00f23468e94f0f0ed6da23f46ed40 Mon Sep 17 00:00:00 2001 From: Ramkumar Radhakrishnan Date: Thu, 16 Aug 2018 15:10:55 -0700 Subject: hwc2: Wait for retire fence after populating it from layer stack Wait for retire fence and notify pmic about secure display end after populating the retire fence from layer stack. Change-Id: I61661d2b4939bbd184aeb8dac310ff156026800c CRs-Fixed: 2298981 --- sdm/libs/hwc2/hwc_display_primary.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'sdm') diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp index 56b612f6..9b5354c3 100644 --- a/sdm/libs/hwc2/hwc_display_primary.cpp +++ b/sdm/libs/hwc2/hwc_display_primary.cpp @@ -445,6 +445,11 @@ HWC2::Error HWCDisplayPrimary::GetReadbackBufferFence(int32_t *release_fence) { } 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) { @@ -456,7 +461,7 @@ HWC2::Error HWCDisplayPrimary::PostCommitLayerStack(int32_t *out_retire_fence) { pmic_intf_->Notify(false /* secure_display_start */); pmic_notification_pending_ = false; } - return HWCDisplay::PostCommitLayerStack(out_retire_fence); + return HWC2::Error::None; } int HWCDisplayPrimary::Perform(uint32_t operation, ...) { -- cgit v1.2.3 From 7ef1a992b71b63d34c84a9a3aea6727e7923232d Mon Sep 17 00:00:00 2001 From: Ramkumar Radhakrishnan Date: Wed, 8 Aug 2018 13:55:08 -0700 Subject: 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 --- sdm/include/core/display_interface.h | 9 +++++ sdm/libs/core/display_base.h | 3 ++ sdm/libs/core/display_primary.cpp | 13 ++++++++ sdm/libs/core/display_primary.h | 1 + sdm/libs/core/drm/hw_device_drm.cpp | 12 +------ sdm/libs/core/drm/hw_device_drm.h | 5 ++- sdm/libs/core/drm/hw_peripheral_drm.cpp | 42 +++++++++++++++++++++++ sdm/libs/core/drm/hw_peripheral_drm.h | 8 +++++ sdm/libs/core/drm/hw_tv_drm.cpp | 14 ++++++++ sdm/libs/core/drm/hw_tv_drm.h | 1 + sdm/libs/core/drm/hw_virtual_drm.cpp | 19 +++++++++++ sdm/libs/core/drm/hw_virtual_drm.h | 1 + sdm/libs/core/fb/hw_device.h | 3 ++ sdm/libs/core/hw_interface.h | 1 + sdm/libs/hwc2/Android.mk | 8 +++++ sdm/libs/hwc2/display_null.h | 1 + sdm/libs/hwc2/hwc_display.h | 3 ++ sdm/libs/hwc2/hwc_display_primary.cpp | 11 ++++++ sdm/libs/hwc2/hwc_display_primary.h | 1 + sdm/libs/hwc2/hwc_session.cpp | 59 ++++++++++++++++++++++++++++----- sdm/libs/hwc2/hwc_session.h | 26 ++++++++++++--- sdm/libs/hwc2/hwc_session_services.cpp | 49 ++++++++++++++++++++++++++- 22 files changed, 263 insertions(+), 27 deletions(-) (limited to 'sdm') 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 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 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 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(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 HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) { - return CallDisplayFunction(static_cast(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(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 +#elif DISPLAY_CONFIG_1_2 +#include +#elif DISPLAY_CONFIG_1_1 #include #else #include @@ -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 setCameraLaunchStatus(uint32_t on) override; Return displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) override; - - // Methods from ::android::hardware::display::config::V1_1::IDisplayConfig follow. #ifdef DISPLAY_CONFIG_1_1 Return 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 setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type, + uint32_t base, uint32_t count) { return 0; } +#endif +#ifdef DISPLAY_CONFIG_1_3 + Return 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 HWCSession::displayBWTransactionPending(displayBWTransactionPending return Void(); } +#ifdef DISPLAY_CONFIG_1_1 +// Methods from ::vendor::hardware::display::config::V1_1::IDisplayConfig follow. +Return HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) { + return CallDisplayFunction(static_cast(this), display_id, + &HWCDisplay::SetDisplayAnimating, animating); +} +#endif + +#ifdef DISPLAY_CONFIG_1_3 +Return 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 -- cgit v1.2.3 From 08f7a64fd5b9a9a7779322d50eca8c9c380129c2 Mon Sep 17 00:00:00 2001 From: Gurpreet Singh Dhami Date: Tue, 21 Aug 2018 12:19:47 -0400 Subject: hwc2: Fix GetDozeSupport api to handle failure case Fix for GetDozeSupport api to return BAD_DISPLAY error, if that display doesn't exist. Change-Id: I53c61d0d0adc3850ef9e82da189c4d8141466c93 --- sdm/libs/hwc2/hwc_session.cpp | 19 ++++++++++++------- sdm/libs/hwc2/hwc_session.h | 2 ++ 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'sdm') diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp index 6520c3ee..d8c633e0 100644 --- a/sdm/libs/hwc2/hwc_session.cpp +++ b/sdm/libs/hwc2/hwc_session.cpp @@ -557,12 +557,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(device); + if (display >= HWC_NUM_DISPLAY_TYPES || (hwc_session->hwc_display_[display] == nullptr) ) { return HWC2_ERROR_BAD_DISPLAY; } @@ -606,7 +608,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 +623,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) { @@ -837,7 +837,12 @@ 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; } diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h index 725e9836..b499e8d9 100644 --- a/sdm/libs/hwc2/hwc_session.h +++ b/sdm/libs/hwc2/hwc_session.h @@ -169,6 +169,8 @@ 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]; -- cgit v1.2.3 From 425545165353f882abbdd6eac0828d3515ef4186 Mon Sep 17 00:00:00 2001 From: Gurpreet Singh Dhami Date: Wed, 29 Aug 2018 16:51:26 -0400 Subject: hwc2: Fix error handling for invalid ColorMode and RenderIntent Fix to return BAD_PARAMETER for invalid RenderIntent value in GetRenderIntents api and invalid ColorMode in SetColorModeWithRenderIntent api. Currently they return Unsupported error. Change-Id: Ic56322f56170d2e421161c69ebf4900f86ec554c --- sdm/libs/hwc2/hwc_session.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'sdm') diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp index aa2c22c7..39c73f85 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); } @@ -700,6 +705,11 @@ int32_t HWCSession::SetColorModeWithRenderIntent(hwc2_device_t *device, hwc2_dis return HWC2_ERROR_BAD_PARAMETER; } auto render_intent = static_cast(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); } @@ -1524,6 +1534,11 @@ android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_ auto mode = static_cast(input_parcel->readInt32()); auto device = static_cast(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; @@ -1538,6 +1553,16 @@ android::status_t HWCSession::SetColorModeWithRenderIntentOverride( auto intent = static_cast(input_parcel->readInt32()); auto device = static_cast(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) -- cgit v1.2.3