sde: Add support to set the display mode of the primary display
The display mode for the primary display can be set to either
command or video mode if the target supports this.
Syntax:
adb shell "service call display.qservice 29 i32 <DISPLAY_MODE>"
DISPLAY_MODE = 1 -> Video
2 -> Command
Change-Id: Iadf4beea8959a90a0b18f8286a094bbbdf18358a
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
index 9aae0a1..f4c4415 100644
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -322,6 +322,14 @@
*/
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages) = 0;
+ /*! @brief Method to set the mode of the primary display.
+
+ @param[in] mode the new display mode.
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetDisplayMode(uint32_t mode) = 0;
+
protected:
virtual ~DisplayInterface() { }
};
diff --git a/displayengine/include/private/hw_info_types.h b/displayengine/include/private/hw_info_types.h
index d842167..c6c2a0a 100644
--- a/displayengine/include/private/hw_info_types.h
+++ b/displayengine/include/private/hw_info_types.h
@@ -87,15 +87,21 @@
void Reset() { *this = HWResourceInfo(); }
};
-/*! @brief This enumeration holds the all possible panel types. */
-enum HWPanelType {
- kNoPanel,
- kCommandModePanel,
- kVideoModePanel,
- kDTvPanel,
- kWriteBackPanel,
- kLVDSPanel,
- kEDPPanel,
+/*! @brief This enumeration holds the possible display modes. */
+enum HWDisplayMode {
+ kModeDefault,
+ kModeVideo,
+ kModeCommand,
+};
+
+/*! @brief This enumeration holds the all possible display port types. */
+enum HWDisplayPort {
+ kPortDefault,
+ kPortDSI,
+ kPortDTv,
+ kPortWriteBack,
+ kPortLVDS,
+ kPortEDP,
};
/*! @brief This structure describes the split configuration of a display panel. */
@@ -103,12 +109,14 @@
uint32_t left_split;
uint32_t right_split;
bool always_src_split;
+
HWSplitInfo() : left_split(0), right_split(0), always_src_split(false) { }
};
/*! @brief This structure describes properties of a display panel. */
struct HWPanelInfo {
- HWPanelType type; //!< Panel type
+ HWDisplayPort port; //!< Display port
+ HWDisplayMode mode; //!< Display mode
bool partial_update; //!< Partial update feature
int left_align; //!< ROI left alignment restriction
int width_align; //!< ROI width alignment restriction
@@ -123,8 +131,8 @@
bool is_primary_panel; //!< Panel is primary display
HWSplitInfo split_info; //!< Panel split configuration
- HWPanelInfo() : type(kNoPanel), partial_update(false), left_align(false), width_align(false),
- top_align(false), height_align(false), min_roi_width(0), min_roi_height(0),
+ HWPanelInfo() : port(kPortDefault), mode(kModeDefault), partial_update(false), left_align(false),
+ width_align(false), top_align(false), height_align(false), min_roi_width(0), min_roi_height(0),
needs_roi_merge(false), dynamic_fps(false), min_fps(0), max_fps(0) { }
};
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 00e707c..e58b4f8 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -371,6 +371,10 @@
return error;
}
+DisplayError DisplayBase::SetDisplayMode(uint32_t mode) {
+ return kErrorNotSupported;
+}
+
void DisplayBase::AppendDump(char *buffer, uint32_t length) {
DumpImpl::AppendString(buffer, length, "\n-----------------------");
DumpImpl::AppendString(buffer, length, "\ndevice type: %u", display_type_);
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index ec90510..6d107a0 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -59,6 +59,7 @@
virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info);
virtual DisplayError SetActiveConfig(uint32_t index);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+ virtual DisplayError SetDisplayMode(uint32_t mode);
protected:
// DumpImpl method
diff --git a/displayengine/libs/core/display_hdmi.cpp b/displayengine/libs/core/display_hdmi.cpp
index 56a12f1..2b6ba81 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -147,6 +147,11 @@
return DisplayBase::SetMaxMixerStages(max_mixer_stages);
}
+DisplayError DisplayHDMI::SetDisplayMode(uint32_t mode) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetDisplayMode(mode);
+}
+
int DisplayHDMI::GetBestConfig() {
uint32_t best_config_mode = 0;
HWDisplayAttributes *best = &display_attributes_[0];
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 8b3cf1b..fc2be21 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -54,6 +54,7 @@
virtual DisplayError SetVSyncState(bool enable);
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+ virtual DisplayError SetDisplayMode(uint32_t mode);
virtual void AppendDump(char *buffer, uint32_t length);
private:
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
index 542b46a..6f705f7 100644
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -61,7 +61,7 @@
}
// Idle fallback feature is supported only for video mode panel.
- if (hw_panel_info_.type == kVideoModePanel) {
+ if (hw_panel_info_.mode == kModeVideo) {
hw_primary_intf_->SetIdleTimeoutMs(Debug::GetIdleTimeoutMs());
}
@@ -87,7 +87,17 @@
DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) {
SCOPE_LOCK(locker_);
- return DisplayBase::Commit(layer_stack);
+ DisplayError error = kErrorNone;
+
+ error = DisplayBase::Commit(layer_stack);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ hw_primary_intf_->GetHWPanelInfo(&hw_panel_info_);
+ // TODO(user): Update panel info in composition manager and resource manager
+
+ return error;
}
DisplayError DisplayPrimary::Flush() {
@@ -156,7 +166,7 @@
void DisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
SCOPE_LOCK(locker_);
// Idle fallback feature is supported only for video mode panel.
- if (hw_panel_info_.type == kVideoModePanel) {
+ if (hw_panel_info_.mode == kModeCommand) {
hw_primary_intf_->SetIdleTimeoutMs(timeout_ms);
}
}
@@ -166,6 +176,44 @@
return DisplayBase::SetMaxMixerStages(max_mixer_stages);
}
+DisplayError DisplayPrimary::SetDisplayMode(uint32_t mode) {
+ SCOPE_LOCK(locker_);
+ DisplayError error = kErrorNone;
+ HWDisplayMode hw_display_mode = kModeDefault;
+
+ if (state_ != kStateOn) {
+ DLOGW("Invalid display state (%d). Panel must be on.", state_);
+ return kErrorNotSupported;
+ }
+
+ switch(mode) {
+ case kModeVideo:
+ hw_display_mode = kModeVideo;
+ break;
+ case kModeCommand:
+ hw_display_mode = kModeCommand;
+ break;
+ default:
+ DLOGW("Invalid panel mode parameters. Requested (%d)", mode);
+ return kErrorParameters;
+ }
+
+ if (hw_display_mode == hw_panel_info_.mode) {
+ DLOGW("Same display mode requested. Current (%d) Requested (%d)", hw_panel_info_.mode,
+ hw_display_mode);
+ return kErrorNone;
+ }
+
+ error = hw_primary_intf_->SetDisplayMode(hw_display_mode);
+ if (error != kErrorNone) {
+ DLOGW("Retaining current display mode. Current (%d), Requested (%d)", hw_panel_info_.mode,
+ hw_display_mode);
+ return error;
+ }
+
+ return error;
+}
+
void DisplayPrimary::AppendDump(char *buffer, uint32_t length) {
SCOPE_LOCK(locker_);
DisplayBase::AppendDump(buffer, length);
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index ea0050a..8ce4f28 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -54,6 +54,7 @@
virtual DisplayError SetVSyncState(bool enable);
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+ virtual DisplayError SetDisplayMode(uint32_t mode);
virtual void AppendDump(char *buffer, uint32_t length);
// Implement the HWEventHandlers
diff --git a/displayengine/libs/core/display_virtual.cpp b/displayengine/libs/core/display_virtual.cpp
index 7430c06..a5af9bf 100644
--- a/displayengine/libs/core/display_virtual.cpp
+++ b/displayengine/libs/core/display_virtual.cpp
@@ -147,6 +147,11 @@
return DisplayBase::SetMaxMixerStages(max_mixer_stages);
}
+DisplayError DisplayVirtual::SetDisplayMode(uint32_t mode) {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::SetDisplayMode(mode);
+}
+
void DisplayVirtual::AppendDump(char *buffer, uint32_t length) {
SCOPE_LOCK(locker_);
DisplayBase::AppendDump(buffer, length);
diff --git a/displayengine/libs/core/display_virtual.h b/displayengine/libs/core/display_virtual.h
index f7ba380..419c6ec 100644
--- a/displayengine/libs/core/display_virtual.h
+++ b/displayengine/libs/core/display_virtual.h
@@ -54,6 +54,7 @@
virtual DisplayError SetVSyncState(bool enable);
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+ virtual DisplayError SetDisplayMode(uint32_t mode);
virtual void AppendDump(char *buffer, uint32_t length);
private:
diff --git a/displayengine/libs/core/fb/hw_device.cpp b/displayengine/libs/core/fb/hw_device.cpp
index ed19d80..093667e 100644
--- a/displayengine/libs/core/fb/hw_device.cpp
+++ b/displayengine/libs/core/fb/hw_device.cpp
@@ -61,7 +61,7 @@
HWDevice::HWDevice(BufferSyncHandler *buffer_sync_handler)
: fb_node_index_(-1), fb_path_("/sys/devices/virtual/graphics/fb"), hotplug_enabled_(false),
- buffer_sync_handler_(buffer_sync_handler) {
+ buffer_sync_handler_(buffer_sync_handler), synchronous_commit_(false) {
// Pointer to actual driver interfaces.
ioctl_ = ::ioctl;
open_ = ::open;
@@ -146,7 +146,7 @@
}
DisplayError HWDevice::GetHWPanelInfo(HWPanelInfo *panel_info) {
- *panel_info = panel_info_;
+ *panel_info = hw_panel_info_;
return kErrorNone;
}
@@ -425,9 +425,13 @@
mdp_commit.release_fence = -1;
mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+ if (synchronous_commit_) {
+ mdp_commit.flags |= MDP_COMMIT_WAIT_FOR_FINISH;
+ }
if (ioctl_(device_fd_, MSMFB_ATOMIC_COMMIT, &mdp_disp_commit_) < 0) {
IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
DumpLayerCommit(mdp_disp_commit_);
+ synchronous_commit_ = false;
return kErrorHardware;
}
@@ -463,6 +467,13 @@
close_(mdp_commit.release_fence);
+ if (synchronous_commit_) {
+ // A synchronous commit can be requested when changing the display mode so we need to update
+ // panel info.
+ PopulateHWPanelInfo();
+ synchronous_commit_ = false;
+ }
+
return kErrorNone;
}
@@ -586,12 +597,12 @@
}
break;
case kDeviceHDMI:
- if (panel_info->type == kDTvPanel) {
+ if (panel_info->port == kPortDTv) {
fb_node_index = i;
}
break;
case kDeviceVirtual:
- if (panel_info->type == kWriteBackPanel) {
+ if (panel_info->port == kPortWriteBack) {
fb_node_index = i;
}
break;
@@ -603,21 +614,23 @@
}
void HWDevice::PopulateHWPanelInfo() {
- panel_info_ = HWPanelInfo();
- GetHWPanelInfoByNode(fb_node_index_, &panel_info_);
- DLOGI("Device type = %d, Panel Type = %d, Device Node = %d, Is Primary = %d",
- device_type_, panel_info_.type, fb_node_index_, panel_info_.is_primary_panel);
+ hw_panel_info_ = HWPanelInfo();
+ GetHWPanelInfoByNode(fb_node_index_, &hw_panel_info_);
+ DLOGI("Device type = %d, Display Port = %d, Display Mode = %d, Device Node = %d, Is Primary = %d",
+ device_type_, hw_panel_info_.port, hw_panel_info_.mode, fb_node_index_,
+ hw_panel_info_.is_primary_panel);
DLOGI("Partial Update = %d, Dynamic FPS = %d",
- panel_info_.partial_update, panel_info_.dynamic_fps);
+ hw_panel_info_.partial_update, hw_panel_info_.dynamic_fps);
DLOGI("Align: left = %d, width = %d, top = %d, height = %d",
- panel_info_.left_align, panel_info_.width_align,
- panel_info_.top_align, panel_info_.height_align);
+ hw_panel_info_.left_align, hw_panel_info_.width_align,
+ hw_panel_info_.top_align, hw_panel_info_.height_align);
DLOGI("ROI: min_width = %d, min_height = %d, need_merge = %d",
- panel_info_.min_roi_width, panel_info_.min_roi_height, panel_info_.needs_roi_merge);
- DLOGI("FPS: min = %d, max =%d", panel_info_.min_fps, panel_info_.max_fps);
- DLOGI("Left Split = %d, Right Split = %d", panel_info_.split_info.left_split,
- panel_info_.split_info.right_split);
- DLOGI("Source Split Always = %d", panel_info_.split_info.always_src_split);
+ hw_panel_info_.min_roi_width, hw_panel_info_.min_roi_height,
+ hw_panel_info_.needs_roi_merge);
+ DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps);
+ DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split,
+ hw_panel_info_.split_info.right_split);
+ DLOGI("Source Split Always = %d", hw_panel_info_.split_info.always_src_split);
}
void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) {
@@ -636,7 +649,7 @@
size_t len = kMaxStringLength;
ssize_t read;
- char *line = stringbuffer;
+ char *line = NULL;
while ((read = getline(&line, &len, fileptr)) != -1) {
uint32_t token_count = 0;
const uint32_t max_count = 10;
@@ -670,45 +683,80 @@
}
}
fclose(fileptr);
- panel_info->type = GetHWPanelType(device_node);
+ free(line);
+ panel_info->port = GetHWDisplayPort(device_node);
+ panel_info->mode = GetHWDisplayMode(device_node);
GetSplitInfo(device_node, panel_info);
}
-HWPanelType HWDevice::GetHWPanelType(int device_node) {
+HWDisplayPort HWDevice::GetHWDisplayPort(int device_node) {
char stringbuffer[kMaxStringLength];
DisplayError error = kErrorNone;
- char *line = stringbuffer;
+ char *line = NULL;
size_t len = kMaxStringLength;
ssize_t read;
- HWPanelType panel_type = kNoPanel;
+ HWDisplayPort port = kPortDefault;
snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_type", fb_path_, device_node);
FILE *fileptr = fopen(stringbuffer, "r");
if (!fileptr) {
DLOGW("File not found %s", stringbuffer);
- return panel_type;
+ return port;
}
read = getline(&line, &len, fileptr);
if (read == -1) {
fclose(fileptr);
- return panel_type;
+ return port;
}
if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
- panel_type = kCommandModePanel;
+ port = kPortDSI;
} else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) {
- panel_type = kVideoModePanel;
+ port = kPortDSI;
} else if ((strncmp(line, "lvds panel", strlen("lvds panel")) == 0)) {
- panel_type = kLVDSPanel;
+ port = kPortLVDS;
} else if ((strncmp(line, "edp panel", strlen("edp panel")) == 0)) {
- panel_type = kEDPPanel;
+ port = kPortEDP;
} else if ((strncmp(line, "dtv panel", strlen("dtv panel")) == 0)) {
- panel_type = kDTvPanel;
+ port = kPortDTv;
} else if ((strncmp(line, "writeback panel", strlen("writeback panel")) == 0)) {
- panel_type = kWriteBackPanel;
+ port = kPortWriteBack;
+ } else {
+ port = kPortDefault;
}
fclose(fileptr);
+ free(line);
+ return port;
+}
- return panel_type;
+HWDisplayMode HWDevice::GetHWDisplayMode(int device_node) {
+ char stringbuffer[kMaxStringLength];
+ DisplayError error = kErrorNone;
+ char *line = NULL;
+ size_t len = kMaxStringLength;
+ ssize_t read;
+ HWDisplayMode mode = kModeDefault;
+
+ snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_type", fb_path_, device_node);
+ FILE *fileptr = fopen(stringbuffer, "r");
+ if (!fileptr) {
+ DLOGW("File not found %s", stringbuffer);
+ return mode;
+ }
+ read = getline(&line, &len, fileptr);
+ if (read == -1) {
+ fclose(fileptr);
+ return mode;
+ }
+ if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
+ mode = kModeCommand;
+ } else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) {
+ mode = kModeVideo;
+ } else {
+ mode = kModeDefault;
+ }
+ fclose(fileptr);
+ free(line);
+ return mode;
}
void HWDevice::GetSplitInfo(int device_node, HWPanelInfo *panel_info) {
@@ -716,7 +764,7 @@
FILE *fileptr = NULL;
size_t len = kMaxStringLength;
ssize_t read;
- char *line = stringbuffer;
+ char *line = NULL;
uint32_t token_count = 0;
const uint32_t max_count = 10;
char *tokens[max_count] = { NULL };
@@ -755,6 +803,7 @@
}
}
fclose(fileptr);
+ free(line);
}
int HWDevice::ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count) {
diff --git a/displayengine/libs/core/fb/hw_device.h b/displayengine/libs/core/fb/hw_device.h
index 2a240c6..07d9e4d 100644
--- a/displayengine/libs/core/fb/hw_device.h
+++ b/displayengine/libs/core/fb/hw_device.h
@@ -84,7 +84,8 @@
// Populates HWPanelInfo based on node index
void PopulateHWPanelInfo();
void GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info);
- HWPanelType GetHWPanelType(int device_node);
+ HWDisplayPort GetHWDisplayPort(int device_node);
+ HWDisplayMode GetHWDisplayMode(int device_node);
void GetSplitInfo(int device_node, HWPanelInfo *panel_info);
int ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count);
mdp_scale_data* GetScaleDataRef(uint32_t index) { return &scale_data_[index]; }
@@ -106,7 +107,7 @@
// Store the Device EventHandler - used for callback
HWEventHandler *event_handler_;
HWResourceInfo hw_resource_;
- HWPanelInfo panel_info_;
+ HWPanelInfo hw_panel_info_;
HWInfoInterface *hw_info_intf_;
int fb_node_index_;
const char *fb_path_;
@@ -119,6 +120,7 @@
mdp_scale_data scale_data_[kMaxSDELayers * 2];
mdp_output_layer mdp_out_layer_;
const char *device_name_;
+ bool synchronous_commit_;
};
} // namespace sde
diff --git a/displayengine/libs/core/fb/hw_primary.cpp b/displayengine/libs/core/fb/hw_primary.cpp
index 0dd0db2..3b22054 100644
--- a/displayengine/libs/core/fb/hw_primary.cpp
+++ b/displayengine/libs/core/fb/hw_primary.cpp
@@ -91,7 +91,7 @@
for (int event = 0; event < kNumDisplayEvents; event++) {
pollfd &poll_fd = poll_fds_[event];
- if ((panel_info_.type == kCommandModePanel) &&
+ if ((hw_panel_info_.mode == kModeCommand) &&
(!strncmp(event_name[event], "idle_notify", strlen("idle_notify")))) {
continue;
}
@@ -196,11 +196,11 @@
(FLOAT(var_screeninfo.yres) * 25.4f) / FLOAT(var_screeninfo.height);
display_attributes->fps = FLOAT(meta_data.data.panel_frame_rate);
display_attributes->vsync_period_ns = UINT32(1000000000L / display_attributes->fps);
- display_attributes->is_device_split = (panel_info_.split_info.left_split ||
+ display_attributes->is_device_split = (hw_panel_info_.split_info.left_split ||
(var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false;
- display_attributes->split_left = panel_info_.split_info.left_split ?
- panel_info_.split_info.left_split : display_attributes->x_pixels / 2;
- display_attributes->always_src_split = panel_info_.split_info.always_src_split;
+ display_attributes->split_left = hw_panel_info_.split_info.left_split ?
+ hw_panel_info_.split_info.left_split : display_attributes->x_pixels / 2;
+ display_attributes->always_src_split = hw_panel_info_.split_info.always_src_split;
return kErrorNone;
}
@@ -368,5 +368,33 @@
return kErrorNone;
}
+DisplayError HWPrimary::SetDisplayMode(const HWDisplayMode hw_display_mode) {
+ DisplayError error = kErrorNone;
+ uint32_t mode = -1;
+
+ switch (hw_display_mode) {
+ case kModeVideo:
+ mode = kModeLPMVideo;
+ break;
+ case kModeCommand:
+ mode = kModeLPMCommand;
+ break;
+ default:
+ DLOGW("Failed to translate SDE display mode %d to a MSMFB_LPM_ENABLE mode",
+ hw_display_mode);
+ return kErrorParameters;
+ }
+
+ if (ioctl_(device_fd_, MSMFB_LPM_ENABLE, &mode) < 0) {
+ IOCTL_LOGE(MSMFB_LPM_ENABLE, device_type_);
+ return kErrorHardware;
+ }
+
+ DLOGI("Triggering display mode change to %d on next commit.", hw_display_mode);
+ synchronous_commit_ = true;
+
+ return kErrorNone;
+}
+
} // namespace sde
diff --git a/displayengine/libs/core/fb/hw_primary.h b/displayengine/libs/core/fb/hw_primary.h
index 8ede12d..b008c92 100644
--- a/displayengine/libs/core/fb/hw_primary.h
+++ b/displayengine/libs/core/fb/hw_primary.h
@@ -52,8 +52,15 @@
virtual DisplayError Flush();
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual DisplayError SetVSyncState(bool enable);
+ virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode);
private:
+ // Panel modes for the MSMFB_LPM_ENABLE ioctl
+ enum {
+ kModeLPMVideo,
+ kModeLPMCommand,
+ };
+
// Event Thread to receive vsync/blank events
static void* DisplayEventThread(void *context);
void* DisplayEventThreadHandler();
diff --git a/displayengine/libs/core/hw_primary_interface.h b/displayengine/libs/core/hw_primary_interface.h
index 31df694..d195348 100644
--- a/displayengine/libs/core/hw_primary_interface.h
+++ b/displayengine/libs/core/hw_primary_interface.h
@@ -37,6 +37,7 @@
static DisplayError Destroy(HWPrimaryInterface *intf);
virtual DisplayError SetVSyncState(bool enable) = 0;
virtual void SetIdleTimeoutMs(uint32_t timeout_ms) = 0;
+ virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode) = 0;
protected:
virtual ~HWPrimaryInterface() { }
diff --git a/displayengine/libs/hwc/hwc_display_primary.cpp b/displayengine/libs/hwc/hwc_display_primary.cpp
index 6dbb723..d1cd2d2 100644
--- a/displayengine/libs/hwc/hwc_display_primary.cpp
+++ b/displayengine/libs/hwc/hwc_display_primary.cpp
@@ -72,5 +72,15 @@
return 0;
}
+DisplayError HWCDisplayPrimary::SetDisplayMode(uint32_t mode) {
+ DisplayError error = kErrorNone;
+
+ if (display_intf_) {
+ error = display_intf_->SetDisplayMode(mode);
+ }
+
+ return error;
+}
+
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_primary.h b/displayengine/libs/hwc/hwc_display_primary.h
index 4e9e93f..5015fff 100644
--- a/displayengine/libs/hwc/hwc_display_primary.h
+++ b/displayengine/libs/hwc/hwc_display_primary.h
@@ -34,6 +34,7 @@
explicit HWCDisplayPrimary(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
virtual int Prepare(hwc_display_contents_1_t *content_list);
virtual int Commit(hwc_display_contents_1_t *content_list);
+ virtual DisplayError SetDisplayMode(uint32_t mode);
};
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index b6d0c18..83e5997 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -588,6 +588,10 @@
status = SetMaxMixerStages(input_parcel);
break;
+ case qService::IQService::SET_DISPLAY_MODE:
+ status = SetDisplayMode(input_parcel);
+ break;
+
default:
DLOGW("QService command = %d is not supported", command);
return -EINVAL;
@@ -596,6 +600,18 @@
return status;
}
+android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
+ DisplayError error = kErrorNone;
+ uint32_t mode = UINT32(input_parcel->readInt32());
+
+ error = display_primary_->SetDisplayMode(mode);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
DisplayError error = kErrorNone;
uint32_t bit_mask_display_type = UINT32(input_parcel->readInt32());
diff --git a/displayengine/libs/hwc/hwc_session.h b/displayengine/libs/hwc/hwc_session.h
index 1608ce5..c22d7bb 100644
--- a/displayengine/libs/hwc/hwc_session.h
+++ b/displayengine/libs/hwc/hwc_session.h
@@ -86,6 +86,7 @@
void DynamicDebug(const android::Parcel *input_parcel);
void SetFrameDumpConfig(const android::Parcel *input_parcel);
android::status_t SetMaxMixerStages(const android::Parcel *input_parcel);
+ android::status_t SetDisplayMode(const android::Parcel *input_parcel);
static Locker locker_;
CoreInterface *core_intf_;
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 40b1ef7..350192d 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -262,6 +262,24 @@
return dpyattr;
}
+int setPanelMode(int mode) {
+ status_t err = (status_t) FAILED_TRANSACTION;
+ sp<IQService> binder = getBinder();
+ if(binder != NULL) {
+ Parcel inParcel, outParcel;
+ inParcel.writeInt32(mode);
+ err = binder->dispatch(IQService::SET_DISPLAY_MODE,
+ &inParcel, &outParcel);
+ if(!err) {
+ ALOGI("%s() Successfully set the display mode to %d", __FUNCTION__,
+ mode);
+ } else {
+ ALOGE("%s() failed with err %d", __FUNCTION__, err);
+ }
+ }
+ return err;
+}
+
//=============================================================================
// The functions/methods below run in the context of HWC and
// are called in response to binder calls from clients
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index 6a66e9f..5ff0862 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -64,6 +64,12 @@
SET_BINDER_DYN_REFRESH_RATE,
};
+enum {
+ DEFAULT_MODE = 0,
+ VIDEO_MODE,
+ COMMAND_MODE,
+};
+
// Display Attributes that are available to clients of this library
// Not to be confused with a similar struct in hwc_utils (in the hwc namespace)
typedef struct DisplayAttributes {
@@ -128,6 +134,9 @@
// Only primary display supported for now, value of dpy ignored
DisplayAttributes getDisplayAttributes(int configIndex, int dpy);
+// Set the primary display mode to command or video mode
+int setDisplayMode(int mode);
+
//=============================================================================
// The functions and methods below run in the context of HWC and
// are called in response to binder calls from clients
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 30578bc..5054578 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -68,6 +68,7 @@
GET_ACTIVE_CONFIG = 26, //Get the current config index
GET_CONFIG_COUNT = 27, //Get the number of supported display configs
GET_DISPLAY_ATTRIBUTES_FOR_CONFIG = 28, //Get attr for specified config
+ SET_DISPLAY_MODE = 29, // Set display mode to command or video mode
COMMAND_LIST_END = 400,
};