sdm: Defer vsync enable/disable when display is powered off
DRM framework rejects vsync enable/disable request when it is requested
before display is powered on. Hence defer the request after display is
powered on.
Change-Id: I3063479c8efc03d87f736a069ad742ae18296fd5
diff --git a/include/display_properties.h b/include/display_properties.h
index 8b0ab16..a5c1378 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -121,6 +121,7 @@
#define VIRTUAL_BASEID_AND_SIZE_PROP DISPLAY_PROP("virtual_baseid_and_size")
#define ENABLE_QDCM_DIAG DISPLAY_PROP("enable_qdcm_diag")
#define QDCM_DISABLE_FACTORY_MODE_PROP DISPLAY_PROP("qdcm.disable_factory_mode")
+#define DISABLE_DEFER_POWER_STATE DISPLAY_PROP("disable_defer_power_state")
#define ZERO_SWAP_INTERVAL "vendor.debug.egl.swapinterval"
#define ENABLE_OPTIMIZE_REFRESH DISPLAY_PROP("enable_optimize_refresh")
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 60e082b..6d63858 100755
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -283,6 +283,14 @@
lock_guard<recursive_mutex> obj(recursive_mutex_);
DisplayError error = kErrorNone;
needs_validate_ = true;
+ if (defer_power_state_ && power_state_pending_ != kStateOff) {
+ defer_power_state_ = false;
+ error = SetDisplayState(power_state_pending_, false, NULL);
+ if (error != kErrorNone) {
+ return error;
+ }
+ power_state_pending_ = kStateOff;
+ }
DTRACE_SCOPED();
if (!active_) {
@@ -516,6 +524,14 @@
DisplayError DisplayBase::SetDisplayState(DisplayState state, bool teardown,
int *release_fence) {
lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (defer_power_state_) {
+ if (state == kStateOff) {
+ DLOGE("State cannot be PowerOff on first cycle");
+ return kErrorParameters;
+ }
+ power_state_pending_ = state;
+ return kErrorNone;
+ }
DisplayError error = kErrorNone;
bool active = false;
@@ -581,6 +597,14 @@
comp_manager_->SetDisplayState(display_comp_ctx_, state, release_fence ? *release_fence : -1);
}
+ if (vsync_state_change_pending_ && (state_ != kStateOff || state_ != kStateStandby)) {
+ error = SetVSyncState(requested_vsync_state_);
+ if (error != kErrorNone) {
+ return error;
+ }
+ vsync_state_change_pending_ = false;
+ }
+
return error;
}
@@ -1092,6 +1116,14 @@
DisplayError DisplayBase::SetVSyncState(bool enable) {
lock_guard<recursive_mutex> obj(recursive_mutex_);
+ if (state_ == kStateOff) {
+ DLOGW("Can't %s vsync when power state is off for display %d-%d," \
+ "Defer it when display is active", enable ? "enable":"disable",
+ display_id_, display_type_);
+ vsync_state_change_pending_ = true;
+ requested_vsync_state_ = enable;
+ return kErrorNone;
+ }
DisplayError error = kErrorNone;
if (vsync_enable_ != enable) {
error = hw_intf_->SetVSyncState(enable);
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index f33acd5..a4f2330 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -232,6 +232,10 @@
uint32_t current_refresh_rate_ = 0;
bool drop_skewed_vsync_ = false;
bool custom_mixer_resolution_ = false;
+ DisplayState power_state_pending_ = kStateOff;
+ bool vsync_state_change_pending_ = false;
+ bool requested_vsync_state_ = false;
+ bool defer_power_state_ = false;
static Locker display_power_reset_lock_;
static bool display_power_reset_pending_;
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index 73b9a9d..153b018 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -56,6 +56,7 @@
DisplayError DisplayBuiltIn::Init() {
lock_guard<recursive_mutex> obj(recursive_mutex_);
+ int32_t disable_defer_power_state = 0;
DisplayError error = HWInterface::Create(display_id_, kBuiltIn, hw_info_intf_,
buffer_sync_handler_, buffer_allocator_, &hw_intf_);
@@ -110,6 +111,11 @@
current_refresh_rate_ = hw_panel_info_.max_fps;
+ Debug::GetProperty(DISABLE_DEFER_POWER_STATE, &disable_defer_power_state);
+ defer_power_state_ = !disable_defer_power_state;
+
+ DLOGI("defer_power_state %d", defer_power_state_);
+
return error;
}
diff --git a/sdm/libs/core/display_pluggable.cpp b/sdm/libs/core/display_pluggable.cpp
index 5bed20a..4e184e8 100644
--- a/sdm/libs/core/display_pluggable.cpp
+++ b/sdm/libs/core/display_pluggable.cpp
@@ -130,6 +130,12 @@
current_refresh_rate_ = hw_panel_info_.max_fps;
+ if (IsPrimaryDisplay()) {
+ int32_t disable_defer_power_state = 0;
+ Debug::GetProperty(DISABLE_DEFER_POWER_STATE, &disable_defer_power_state);
+ defer_power_state_ = !disable_defer_power_state;
+ }
+
return error;
}
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 2211e07..a9531c7 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -900,17 +900,27 @@
int64_t release_fence_t = -1;
update_mode_ = true;
+
+ if (first_cycle_) {
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, token_.conn_id, token_.crtc_id);
+ drmModeModeInfo current_mode = connector_info_.modes[current_mode_index_].mode;
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, ¤t_mode);
+ }
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);
- drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence_t);
+ if (release_fence) {
+ drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence_t);
+ }
int ret = NullCommit(true /* synchronous */, true /* retain_planes */);
if (ret) {
DLOGE("Failed with error: %d", ret);
return kErrorHardware;
}
- *release_fence = static_cast<int>(release_fence_t);
- DLOGD_IF(kTagDriverConfig, "RELEASE fence created: fd:%d", *release_fence);
+ if (release_fence) {
+ *release_fence = static_cast<int>(release_fence_t);
+ DLOGD_IF(kTagDriverConfig, "RELEASE fence created: fd:%d", *release_fence);
+ }
pending_doze_ = false;
return kErrorNone;
@@ -960,15 +970,19 @@
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::DOZE);
- drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence_t);
+ if (release_fence) {
+ drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence_t);
+ }
int ret = NullCommit(true /* synchronous */, true /* retain_planes */);
if (ret) {
DLOGE("Failed with error: %d", ret);
return kErrorHardware;
}
- *release_fence = static_cast<int>(release_fence_t);
- DLOGD_IF(kTagDriverConfig, "RELEASE fence created: fd:%d", *release_fence);
+ if (release_fence) {
+ *release_fence = static_cast<int>(release_fence_t);
+ DLOGD_IF(kTagDriverConfig, "RELEASE fence created: fd:%d", *release_fence);
+ }
return kErrorNone;
}
@@ -987,17 +1001,21 @@
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::DOZE_SUSPEND);
- drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence_t);
+ if (release_fence) {
+ drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, &release_fence_t);
+ }
int ret = NullCommit(true /* synchronous */, true /* retain_planes */);
if (ret) {
DLOGE("Failed with error: %d", ret);
return kErrorHardware;
}
- *release_fence = static_cast<int>(release_fence_t);
- DLOGD_IF(kTagDriverConfig, "RELEASE fence created: fd:%d", *release_fence);
- pending_doze_ = false;
+ if (release_fence) {
+ *release_fence = static_cast<int>(release_fence_t);
+ DLOGD_IF(kTagDriverConfig, "RELEASE fence created: fd:%d", *release_fence);
+ }
+ pending_doze_ = false;
return kErrorNone;
}
@@ -1241,7 +1259,7 @@
}
// Set CRTC mode, only if display config changes
- if (vrefresh_ || first_cycle_ || update_mode_) {
+ if (vrefresh_ || update_mode_) {
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, ¤t_mode);
}
diff --git a/sdm/libs/core/drm/hw_events_drm.cpp b/sdm/libs/core/drm/hw_events_drm.cpp
index e63605e..3bb9a6a 100644
--- a/sdm/libs/core/drm/hw_events_drm.cpp
+++ b/sdm/libs/core/drm/hw_events_drm.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -222,8 +222,6 @@
return kErrorResources;
}
- RegisterVSync();
- vsync_registered_ = true;
RegisterPanelDead(true);
RegisterIdleNotify(true);
RegisterIdlePowerCollapse(true);
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
index ec865fe..b7771a0 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.cpp
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -436,9 +436,6 @@
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(qos_data, release_fence);
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index ad39b86..4b2dc89 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -356,10 +356,6 @@
return kErrorUndefined;
}
- if (first_cycle_) {
- return kErrorNone;
- }
-
return HWDeviceDRM::PowerOn(qos_data, release_fence);
}
diff --git a/sdm/libs/core/drm/hw_virtual_drm.cpp b/sdm/libs/core/drm/hw_virtual_drm.cpp
index 152e28c..97b77e0 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.cpp
+++ b/sdm/libs/core/drm/hw_virtual_drm.cpp
@@ -233,10 +233,6 @@
return kErrorUndefined;
}
- if (first_cycle_) {
- return kErrorNone;
- }
-
DisplayError err = HWDeviceDRM::PowerOn(qos_data, release_fence);
if (err != kErrorNone) {
return err;