sdm: add support for POMS in and out of doze mode transitions
Change-Id: I24c518df4ed38c246c938dea3f064a851c665483
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 75f6136..cc2855e 100755
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -617,6 +617,11 @@
return kErrorParameters;
}
+ error = ReconfigureDisplay();
+ if (error != kErrorNone) {
+ return error;
+ }
+
DisablePartialUpdateOneFrame();
if (error == kErrorNone) {
@@ -2006,6 +2011,11 @@
if (pending_doze_) {
state_ = kStateDoze;
+ DisplayError error = ReconfigureDisplay();
+ if (error != kErrorNone) {
+ return error;
+ }
+ event_handler_->Refresh();
}
if (pending_power_on_) {
state_ = kStateOn;
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index 5ab5e51..2bd9004 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -193,6 +193,7 @@
lock_guard<recursive_mutex> obj(recursive_mutex_);
DisplayError error = kErrorNone;
uint32_t app_layer_count = hw_layers_.info.app_layer_count;
+ HWDisplayMode panel_mode = hw_panel_info_.mode;
DTRACE_SCOPED();
@@ -251,6 +252,9 @@
ControlPartialUpdate(true /* enable */, &pending);
}
+ if (panel_mode != hw_panel_info_.mode) {
+ UpdateDisplayModeParams();
+ }
dpps_info_.Init(this, hw_panel_info_.panel_name);
if (qsync_mode_ == kQsyncModeOneShot) {
@@ -272,10 +276,22 @@
return error;
}
+void DisplayBuiltIn::UpdateDisplayModeParams() {
+ if (hw_panel_info_.mode == kModeVideo) {
+ uint32_t pending = 0;
+ ControlPartialUpdate(false /* enable */, &pending);
+ } else if (hw_panel_info_.mode == kModeCommand) {
+ // Flush idle timeout value currently set.
+ comp_manager_->SetIdleTimeoutMs(display_comp_ctx_, 0);
+ switch_to_cmd_ = true;
+ }
+}
+
DisplayError DisplayBuiltIn::SetDisplayState(DisplayState state, bool teardown,
int *release_fence) {
lock_guard<recursive_mutex> obj(recursive_mutex_);
DisplayError error = kErrorNone;
+ HWDisplayMode panel_mode = hw_panel_info_.mode;
if ((state == kStateOn) && deferred_config_.IsDeferredState()) {
SetDeferredFpsConfig();
@@ -286,6 +302,10 @@
return error;
}
+ if (hw_panel_info_.mode != panel_mode) {
+ UpdateDisplayModeParams();
+ }
+
// Set vsync enable state to false, as driver disables vsync during display power off.
if (state == kStateOff) {
vsync_enable_ = false;
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index 8d54df6..6da7a87 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -145,6 +145,7 @@
bool CanDeferFpsConfig(uint32_t fps);
void SetDeferredFpsConfig();
void GetFpsConfig(HWDisplayAttributes *display_attributes, HWPanelInfo *panel_info);
+ void UpdateDisplayModeParams();
std::vector<HWEvent> event_list_;
bool avr_prop_disabled_ = false;
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index e8cea73..007cb2a 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -572,6 +572,7 @@
}
PopulateDisplayAttributes(i);
}
+ SetDisplaySwitchMode(current_mode_index_);
}
DisplayError HWDeviceDRM::PopulateDisplayAttributes(uint32_t index) {
@@ -838,22 +839,20 @@
return kErrorNone;
}
-DisplayError HWDeviceDRM::SetDisplayAttributes(uint32_t index) {
- if (index >= display_attributes_.size()) {
- DLOGE("Invalid mode index %d mode size %d", index, UINT32(display_attributes_.size()));
- return kErrorParameters;
- }
-
+void HWDeviceDRM::SetDisplaySwitchMode(uint32_t index) {
uint32_t mode_flag = 0;
- uint32_t curr_mode_flag = 0;
+ uint32_t curr_mode_flag = 0, switch_mode_flag = 0;
drmModeModeInfo to_set = connector_info_.modes[index].mode;
drmModeModeInfo current_mode = connector_info_.modes[current_mode_index_].mode;
uint64_t current_bit_clk = connector_info_.modes[current_mode_index_].bit_clk_rate;
+ uint32_t switch_index = 0;
if (to_set.flags & DRM_MODE_FLAG_CMD_MODE_PANEL) {
mode_flag = DRM_MODE_FLAG_CMD_MODE_PANEL;
+ switch_mode_flag = DRM_MODE_FLAG_VID_MODE_PANEL;
} else if (to_set.flags & DRM_MODE_FLAG_VID_MODE_PANEL) {
mode_flag = DRM_MODE_FLAG_VID_MODE_PANEL;
+ switch_mode_flag = DRM_MODE_FLAG_CMD_MODE_PANEL;
}
if (current_mode.flags & DRM_MODE_FLAG_CMD_MODE_PANEL) {
@@ -878,21 +877,70 @@
}
current_mode_index_ = index;
+
+ switch_mode_valid_ = false;
+ for (uint32_t mode_index = 0; mode_index < connector_info_.modes.size(); mode_index++) {
+ if ((to_set.vdisplay == connector_info_.modes[mode_index].mode.vdisplay) &&
+ (to_set.hdisplay == connector_info_.modes[mode_index].mode.hdisplay) &&
+ (to_set.vrefresh == connector_info_.modes[mode_index].mode.vrefresh) &&
+ (switch_mode_flag & connector_info_.modes[mode_index].mode.flags)) {
+ switch_index = mode_index;
+ switch_mode_valid_ = true;
+ break;
+ }
+ }
+
+ if (!switch_mode_valid_) {
+ // in case there is no corresponding switch mode with same fps, try for a switch
+ // mode with lowest fps. This is to handle cases where there are multiple video mode fps
+ // but only one command mode for doze like 30 fps.
+ uint32_t refresh_rate = 0;
+ for (uint32_t mode_index = 0; mode_index < connector_info_.modes.size(); mode_index++) {
+ if ((to_set.vdisplay == connector_info_.modes[mode_index].mode.vdisplay) &&
+ (to_set.hdisplay == connector_info_.modes[mode_index].mode.hdisplay) &&
+ (switch_mode_flag & connector_info_.modes[mode_index].mode.flags)) {
+ if (!refresh_rate || (refresh_rate > connector_info_.modes[mode_index].mode.vrefresh)) {
+ switch_index = mode_index;
+ switch_mode_valid_ = true;
+ refresh_rate = connector_info_.modes[mode_index].mode.vrefresh;
+ }
+ }
+ }
+ }
+
+ if (switch_mode_valid_) {
+ if (mode_flag & DRM_MODE_FLAG_VID_MODE_PANEL) {
+ video_mode_index_ = current_mode_index_;
+ cmd_mode_index_ = switch_index;
+ } else {
+ video_mode_index_ = switch_index;
+ cmd_mode_index_ = current_mode_index_;
+ }
+ }
+}
+
+DisplayError HWDeviceDRM::SetDisplayAttributes(uint32_t index) {
+ if (index >= display_attributes_.size()) {
+ DLOGE("Invalid mode index %d mode size %d", index, UINT32(display_attributes_.size()));
+ return kErrorParameters;
+ }
+
+ SetDisplaySwitchMode(index);
PopulateHWPanelInfo();
UpdateMixerAttributes();
- DLOGI_IF(
- kTagDisplay,
- "Display attributes[%d]: WxH: %dx%d, DPI: %fx%f, FPS: %d, LM_SPLIT: %d, V_BACK_PORCH: %d,"
- " V_FRONT_PORCH: %d, V_PULSE_WIDTH: %d, V_TOTAL: %d, H_TOTAL: %d, CLK: %dKHZ,"
- "TOPOLOGY: %d, PanelMode %s", index, display_attributes_[index].x_pixels,
- display_attributes_[index].y_pixels, display_attributes_[index].x_dpi,
- display_attributes_[index].y_dpi, display_attributes_[index].fps,
- display_attributes_[index].is_device_split, display_attributes_[index].v_back_porch,
- display_attributes_[index].v_front_porch, display_attributes_[index].v_pulse_width,
- display_attributes_[index].v_total, display_attributes_[index].h_total,
- display_attributes_[index].clock_khz, display_attributes_[index].topology,
- (mode_flag & DRM_MODE_FLAG_VID_MODE_PANEL) ? "Video" : "Command");
+ DLOGI_IF(kTagDriverConfig,
+ "Display attributes[%d]: WxH: %dx%d, DPI: %fx%f, FPS: %d, LM_SPLIT: %d, V_BACK_PORCH: %d," \
+ " V_FRONT_PORCH: %d, V_PULSE_WIDTH: %d, V_TOTAL: %d, H_TOTAL: %d, CLK: %dKHZ, " \
+ "TOPOLOGY: %d, PanelMode %s", index, display_attributes_[index].x_pixels,
+ display_attributes_[index].y_pixels, display_attributes_[index].x_dpi,
+ display_attributes_[index].y_dpi, display_attributes_[index].fps,
+ display_attributes_[index].is_device_split, display_attributes_[index].v_back_porch,
+ display_attributes_[index].v_front_porch, display_attributes_[index].v_pulse_width,
+ display_attributes_[index].v_total, display_attributes_[index].h_total,
+ display_attributes_[index].clock_khz, display_attributes_[index].topology,
+ (connector_info_.modes[index].mode.flags & DRM_MODE_FLAG_VID_MODE_PANEL) ?
+ "Video" : "Command");
return kErrorNone;
}
@@ -1479,6 +1527,7 @@
(current_bit_clk == connector_info_.modes[mode_index].bit_clk_rate) &&
(vrefresh_ == connector_info_.modes[mode_index].mode.vrefresh)) {
current_mode_index_ = mode_index;
+ SetDisplaySwitchMode(mode_index);
break;
}
}
@@ -1494,6 +1543,7 @@
(current_mode.vrefresh == connector_info_.modes[mode_index].mode.vrefresh) &&
(bit_clk_rate_ == connector_info_.modes[mode_index].bit_clk_rate)) {
current_mode_index_ = mode_index;
+ SetDisplaySwitchMode(mode_index);
break;
}
}
@@ -1715,31 +1765,25 @@
}
DisplayError HWDeviceDRM::SetDisplayMode(const HWDisplayMode hw_display_mode) {
- uint32_t mode_flag;
+ if (!switch_mode_valid_) {
+ return kErrorNotSupported;
+ }
+
+ uint32_t mode_flag = 0;
if (hw_display_mode == kModeCommand) {
mode_flag = DRM_MODE_FLAG_CMD_MODE_PANEL;
- DLOGI("switch panel mode to command");
+ current_mode_index_ = cmd_mode_index_;
+ DLOGI_IF(kTagDriverConfig, "switch panel mode to command");
} else if (hw_display_mode == kModeVideo) {
mode_flag = DRM_MODE_FLAG_VID_MODE_PANEL;
- DLOGI("switch panel mode to video");
+ current_mode_index_ = video_mode_index_;
+ DLOGI_IF(kTagDriverConfig, "switch panel mode to video");
}
-
- drmModeModeInfo current_mode = connector_info_.modes[current_mode_index_].mode;
- for (uint32_t mode_index = 0; mode_index < connector_info_.modes.size(); mode_index++) {
- if ((current_mode.vdisplay == connector_info_.modes[mode_index].mode.vdisplay) &&
- (current_mode.hdisplay == connector_info_.modes[mode_index].mode.hdisplay) &&
- (current_mode.vrefresh == connector_info_.modes[mode_index].mode.vrefresh) &&
- (mode_flag & connector_info_.modes[mode_index].mode.flags)) {
- current_mode_index_ = mode_index;
- PopulateHWPanelInfo();
- panel_mode_changed_ = mode_flag;
- synchronous_commit_ = true;
- return kErrorNone;
- }
- }
-
- return kErrorNotSupported;
+ PopulateHWPanelInfo();
+ panel_mode_changed_ = mode_flag;
+ synchronous_commit_ = true;
+ return kErrorNone;
}
DisplayError HWDeviceDRM::SetRefreshRate(uint32_t refresh_rate) {
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 8b8ca5b..5933347 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -227,10 +227,18 @@
bool reset_output_fence_offset_ = false;
uint64_t bit_clk_rate_ = 0;
bool update_mode_ = false;
+ uint32_t video_mode_index_ = 0;
+ uint32_t cmd_mode_index_ = 0;
+ bool switch_mode_valid_ = false;
+ bool doze_poms_switch_done_ = false;
+ bool pending_poms_switch_ = false;
+ bool active_ = false;
DRMPowerMode last_power_mode_ = DRMPowerMode::OFF;
bool pending_doze_ = false;
private:
+ void SetDisplaySwitchMode(uint32_t index);
+
std::string interface_str_ = "DSI";
bool resolution_switch_enabled_ = false;
bool autorefresh_ = false;
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
index 64109ec..85ec982 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.cpp
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -105,6 +105,10 @@
return kErrorNotSupported;
}
+ if (doze_poms_switch_done_ || pending_poms_switch_) {
+ return kErrorNotSupported;
+ }
+
bit_clk_rate_ = bit_clk_rate;
update_mode_ = true;
@@ -118,7 +122,27 @@
return kErrorNone;
}
+
+DisplayError HWPeripheralDRM::SetRefreshRate(uint32_t refresh_rate) {
+ if (doze_poms_switch_done_ || pending_poms_switch_) {
+ // poms switch in progress
+ // Defer any refresh rate setting.
+ return kErrorNotSupported;
+ }
+
+ DisplayError error = HWDeviceDRM::SetRefreshRate(refresh_rate);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ return kErrorNone;
+}
+
DisplayError HWPeripheralDRM::SetDisplayMode(const HWDisplayMode hw_display_mode) {
+ if (doze_poms_switch_done_ || pending_poms_switch_) {
+ return kErrorNotSupported;
+ }
+
DisplayError error = HWDeviceDRM::SetDisplayMode(hw_display_mode);
if (error != kErrorNone) {
return error;
@@ -156,6 +180,15 @@
// Initialize to default after successful commit
synchronous_commit_ = false;
+ active_ = true;
+
+ if (pending_poms_switch_) {
+ HWDeviceDRM::SetDisplayMode(kModeCommand);
+ hw_panel_info_.bitclk_rates = bitclk_rates_;
+ doze_poms_switch_done_ = true;
+ pending_poms_switch_ = false;
+ }
+
idle_pc_state_ = sde_drm::DRMIdlePCState::NONE;
return error;
@@ -463,6 +496,12 @@
return kErrorDeferred;
}
+ if (switch_mode_valid_ && doze_poms_switch_done_ && (current_mode_index_ == cmd_mode_index_)) {
+ HWDeviceDRM::SetDisplayMode(kModeVideo);
+ hw_panel_info_.bitclk_rates = bitclk_rates_;
+ doze_poms_switch_done_ = false;
+ }
+
if (!idle_pc_enabled_) {
drm_atomic_intf_->Perform(sde_drm::DRMOps::CRTC_SET_IDLE_PC_STATE, token_.crtc_id,
sde_drm::DRMIdlePCState::ENABLE);
@@ -473,11 +512,78 @@
}
idle_pc_state_ = sde_drm::DRMIdlePCState::NONE;
idle_pc_enabled_ = true;
+ pending_poms_switch_ = false;
+ active_ = true;
+
+ return kErrorNone;
+}
+
+DisplayError HWPeripheralDRM::PowerOff(bool teardown) {
+ DTRACE_SCOPED();
+
+ DisplayError err = HWDeviceDRM::PowerOff(teardown);
+ if (err != kErrorNone) {
+ return err;
+ }
+
+ pending_poms_switch_ = false;
+ active_ = false;
+
+ return kErrorNone;
+}
+
+DisplayError HWPeripheralDRM::Doze(const HWQosData &qos_data, int *release_fence) {
+ DTRACE_SCOPED();
+
+ if (!first_cycle_ && switch_mode_valid_ && !doze_poms_switch_done_ &&
+ (current_mode_index_ == video_mode_index_)) {
+ if (active_) {
+ HWDeviceDRM::SetDisplayMode(kModeCommand);
+ hw_panel_info_.bitclk_rates = bitclk_rates_;
+ doze_poms_switch_done_ = true;
+ } else {
+ pending_poms_switch_ = true;
+ }
+ }
+
+ DisplayError err = HWDeviceDRM::Doze(qos_data, release_fence);
+ if (err != kErrorNone) {
+ return err;
+ }
+
+ if (first_cycle_) {
+ active_ = true;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWPeripheralDRM::DozeSuspend(const HWQosData &qos_data, int *release_fence) {
+ DTRACE_SCOPED();
+
+ if (switch_mode_valid_ && !doze_poms_switch_done_ &&
+ (current_mode_index_ == video_mode_index_)) {
+ HWDeviceDRM::SetDisplayMode(kModeCommand);
+ hw_panel_info_.bitclk_rates = bitclk_rates_;
+ doze_poms_switch_done_ = true;
+ }
+
+ DisplayError err = HWDeviceDRM::DozeSuspend(qos_data, release_fence);
+ if (err != kErrorNone) {
+ return err;
+ }
+
+ pending_poms_switch_ = false;
+ active_ = true;
return kErrorNone;
}
DisplayError HWPeripheralDRM::SetDisplayAttributes(uint32_t index) {
+ if (doze_poms_switch_done_ || pending_poms_switch_) {
+ return kErrorNotSupported;
+ }
+
HWDeviceDRM::SetDisplayAttributes(index);
// update bit clk rates.
hw_panel_info_.bitclk_rates = bitclk_rates_;
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.h b/sdm/libs/core/drm/hw_peripheral_drm.h
index 5800e27..92aa90d 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.h
+++ b/sdm/libs/core/drm/hw_peripheral_drm.h
@@ -57,11 +57,15 @@
virtual DisplayError HandleSecureEvent(SecureEvent secure_event, HWLayers *hw_layers);
virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous);
virtual DisplayError PowerOn(const HWQosData &qos_data, int *release_fence);
+ virtual DisplayError PowerOff(bool teardown);
+ virtual DisplayError Doze(const HWQosData &qos_data, int *release_fence);
+ virtual DisplayError DozeSuspend(const HWQosData &qos_data, int *release_fence);
virtual DisplayError SetDisplayDppsAdROI(void *payload);
virtual DisplayError SetDynamicDSIClock(uint64_t bit_clk_rate);
virtual DisplayError GetDynamicDSIClock(uint64_t *bit_clk_rate);
virtual DisplayError SetDisplayAttributes(uint32_t index);
virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode);
+ virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
virtual DisplayError TeardownConcurrentWriteback(void);
virtual DisplayError SetPanelBrightness(int level);
virtual DisplayError GetPanelBrightness(int *level);
diff --git a/sdm/libs/hwc2/hwc_display_builtin.cpp b/sdm/libs/hwc2/hwc_display_builtin.cpp
index d440893..e25e40c 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.cpp
+++ b/sdm/libs/hwc2/hwc_display_builtin.cpp
@@ -310,6 +310,28 @@
return skip_commit;
}
+void HWCDisplayBuiltIn::SetPartialUpdate(DisplayConfigFixedInfo fixed_info) {
+ partial_update_enabled_ = fixed_info.partial_update || (!fixed_info.is_cmdmode);
+ for (auto hwc_layer : layer_set_) {
+ hwc_layer->SetPartialUpdate(partial_update_enabled_);
+ }
+ client_target_->SetPartialUpdate(partial_update_enabled_);
+}
+
+HWC2::Error HWCDisplayBuiltIn::SetPowerMode(HWC2::PowerMode mode, bool teardown) {
+ DisplayConfigFixedInfo fixed_info = {};
+ display_intf_->GetConfig(&fixed_info);
+ bool command_mode = fixed_info.is_cmdmode;
+
+ display_intf_->GetConfig(&fixed_info);
+ is_cmd_mode_ = fixed_info.is_cmdmode;
+ if (is_cmd_mode_ != command_mode) {
+ SetPartialUpdate(fixed_info);
+ }
+
+ return HWC2::Error::None;
+}
+
HWC2::Error HWCDisplayBuiltIn::Present(int32_t *out_retire_fence) {
auto status = HWC2::Error::None;
@@ -329,12 +351,24 @@
DLOGE("Flush failed. Error = %d", error);
}
} else {
+ DisplayConfigFixedInfo fixed_info = {};
+ display_intf_->GetConfig(&fixed_info);
+ bool command_mode = fixed_info.is_cmdmode;
+
status = CommitLayerStack();
if (status == HWC2::Error::None) {
HandleFrameOutput();
SolidFillCommit();
status = PostCommitLayerStack(out_retire_fence);
}
+
+ if (status == HWC2::Error::None) {
+ display_intf_->GetConfig(&fixed_info);
+ is_cmd_mode_ = fixed_info.is_cmdmode;
+ if (is_cmd_mode_ != command_mode) {
+ SetPartialUpdate(fixed_info);
+ }
+ }
}
CloseFd(&output_buffer_.acquire_fence_fd);
diff --git a/sdm/libs/hwc2/hwc_display_builtin.h b/sdm/libs/hwc2/hwc_display_builtin.h
index 8f812db..5c75dc7 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.h
+++ b/sdm/libs/hwc2/hwc_display_builtin.h
@@ -100,6 +100,7 @@
virtual HWC2::Error UpdatePowerMode(HWC2::PowerMode mode);
virtual HWC2::Error PostCommitLayerStack(int32_t *out_retire_fence);
virtual bool IsSmartPanelConfig(uint32_t config_id);
+ virtual HWC2::Error SetPowerMode(HWC2::PowerMode mode, bool teardown);
private:
HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
@@ -118,6 +119,7 @@
bool CanSkipCommit();
DisplayError SetMixerResolution(uint32_t width, uint32_t height);
DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+ void SetPartialUpdate(DisplayConfigFixedInfo fixed_info);
class PMICInterface {
public:
PMICInterface() { }