Merge "sde: Add support to read HDMI scan info"
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
index f8f2701..3042eb2 100644
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -349,6 +349,12 @@
*/
virtual DisplayError SetRefreshRate(uint32_t refresh_rate) = 0;
+ /*! @brief Method to query whether scanning is support for the HDMI display.
+
+ @return \link DisplayError \endlink
+ */
+ virtual bool IsUnderscanSupported() = 0;
+
protected:
virtual ~DisplayInterface() { }
};
diff --git a/displayengine/include/private/hw_info_types.h b/displayengine/include/private/hw_info_types.h
index 58293a7..03a77ae 100644
--- a/displayengine/include/private/hw_info_types.h
+++ b/displayengine/include/private/hw_info_types.h
@@ -106,6 +106,24 @@
kPortEDP,
};
+/*! @brief This enumeration holds the all possible scan types. */
+enum HWScanSupport {
+ kScanNotSupported,
+ kScanAlwaysOverscanned,
+ kScanAlwaysUnderscanned,
+ kScanBoth,
+};
+
+/*! @brief This structure holds the scan support for different timing modes. */
+struct HWScanInfo {
+ HWScanSupport pt_scan_support; //!< Scan support for preferred timing
+ HWScanSupport it_scan_support; //!< Scan support for digital monitor or industry timings
+ HWScanSupport cea_scan_support; //!< Scan support for CEA resolution timings
+
+ HWScanInfo() : pt_scan_support(kScanNotSupported), it_scan_support(kScanNotSupported),
+ cea_scan_support(kScanNotSupported) { }
+};
+
/*! @brief This structure describes the split configuration of a display panel. */
struct HWSplitInfo {
uint32_t left_split;
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index dab3e91..b64eae7 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -41,7 +41,7 @@
buffer_sync_handler_(buffer_sync_handler), comp_manager_(comp_manager),
rotator_ctrl_(rotator_ctrl), state_(kStateOff), hw_device_(0), display_comp_ctx_(0),
display_attributes_(NULL), num_modes_(0), active_mode_index_(0), pending_commit_(false),
- vsync_enable_(false) {
+ vsync_enable_(false), underscan_supported_(false) {
}
DisplayError DisplayBase::Init() {
@@ -290,6 +290,10 @@
return kErrorNone;
}
+bool DisplayBase::IsUnderscanSupported() {
+ return underscan_supported_;
+}
+
DisplayError DisplayBase::SetDisplayState(DisplayState state) {
DisplayError error = kErrorNone;
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 848dea1..ef1ea1f 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -59,6 +59,7 @@
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
virtual DisplayError SetDisplayMode(uint32_t mode);
virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+ virtual bool IsUnderscanSupported();
protected:
// DumpImpl method
@@ -87,6 +88,7 @@
HWLayers hw_layers_;
bool pending_commit_;
bool vsync_enable_;
+ bool underscan_supported_;
};
} // namespace sde
diff --git a/displayengine/libs/core/display_hdmi.cpp b/displayengine/libs/core/display_hdmi.cpp
index 22c97b5..a36f2f2 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -60,6 +60,9 @@
HWHDMIInterface::Destroy(hw_hdmi_intf_);
}
+ GetScanSupport();
+ underscan_supported_ = (scan_support_ == kScanAlwaysUnderscanned) || (scan_support_ == kScanBoth);
+
return error;
}
@@ -163,6 +166,11 @@
return kErrorNotSupported;
}
+bool DisplayHDMI::IsUnderscanSupported() {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::IsUnderscanSupported();
+}
+
int DisplayHDMI::GetBestConfig() {
uint32_t best_config_mode = 0;
HWDisplayAttributes *best = &display_attributes_[0];
@@ -204,6 +212,36 @@
return best_config_mode;
}
+void DisplayHDMI::GetScanSupport() {
+ DisplayError error = kErrorNone;
+ uint32_t video_format = -1;
+ uint32_t max_cea_format = -1;
+ HWScanInfo scan_info = HWScanInfo();
+ hw_hdmi_intf_->GetHWScanInfo(&scan_info);
+
+ error = hw_hdmi_intf_->GetVideoFormat(active_mode_index_, &video_format);
+ if (error != kErrorNone) {
+ return;
+ }
+
+ error = hw_hdmi_intf_->GetMaxCEAFormat(&max_cea_format);
+ if (error != kErrorNone) {
+ return;
+ }
+
+ // The scan support for a given HDMI TV must be read from scan info corresponding to
+ // Preferred Timing if the preferred timing of the display is currently active, and if it is
+ // valid. In all other cases, we must read the scan support from CEA scan info if
+ // the resolution is a CEA resolution, or from IT scan info for all other resolutions.
+ if (active_mode_index_ == 0 && scan_info.pt_scan_support != kScanNotSupported) {
+ scan_support_ = scan_info.pt_scan_support;
+ } else if (video_format < max_cea_format) {
+ scan_support_ = scan_info.cea_scan_support;
+ } else {
+ scan_support_ = scan_info.it_scan_support;
+ }
+}
+
void DisplayHDMI::AppendDump(char *buffer, uint32_t length) {
SCOPE_LOCK(locker_);
DisplayBase::AppendDump(buffer, length);
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index ea60c41..b5a25cc 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -58,14 +58,17 @@
virtual DisplayError SetDisplayMode(uint32_t mode);
virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+ virtual bool IsUnderscanSupported();
virtual void AppendDump(char *buffer, uint32_t length);
private:
virtual int GetBestConfig();
+ virtual void GetScanSupport();
Locker locker_;
HWHDMIInterface *hw_hdmi_intf_;
HWInfoInterface *hw_info_intf_;
+ HWScanSupport scan_support_;
};
} // namespace sde
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
index a196026..8c56799 100644
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -146,6 +146,11 @@
return DisplayBase::GetVSyncState(enabled);
}
+bool DisplayPrimary::IsUnderscanSupported() {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::IsUnderscanSupported();
+}
+
DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
SCOPE_LOCK(locker_);
return DisplayBase::SetDisplayState(state);
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index 2879aa8..11f9687 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -58,6 +58,7 @@
virtual DisplayError SetDisplayMode(uint32_t mode);
virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+ virtual bool IsUnderscanSupported();
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 a4587c3..30588dc 100644
--- a/displayengine/libs/core/display_virtual.cpp
+++ b/displayengine/libs/core/display_virtual.cpp
@@ -120,6 +120,11 @@
return DisplayBase::GetVSyncState(enabled);
}
+bool DisplayVirtual::IsUnderscanSupported() {
+ SCOPE_LOCK(locker_);
+ return DisplayBase::IsUnderscanSupported();
+}
+
DisplayError DisplayVirtual::SetDisplayState(DisplayState state) {
SCOPE_LOCK(locker_);
return DisplayBase::SetDisplayState(state);
diff --git a/displayengine/libs/core/display_virtual.h b/displayengine/libs/core/display_virtual.h
index d6c0fbf..6350e26 100644
--- a/displayengine/libs/core/display_virtual.h
+++ b/displayengine/libs/core/display_virtual.h
@@ -58,6 +58,7 @@
virtual DisplayError SetDisplayMode(uint32_t mode);
virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+ virtual bool IsUnderscanSupported();
virtual void AppendDump(char *buffer, uint32_t length);
private:
diff --git a/displayengine/libs/core/fb/hw_device.h b/displayengine/libs/core/fb/hw_device.h
index 18c6652..e25709e 100644
--- a/displayengine/libs/core/fb/hw_device.h
+++ b/displayengine/libs/core/fb/hw_device.h
@@ -29,7 +29,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <linux/msm_mdp_ext.h>
-#include <video/msm_hdmi_modes.h>
#include <linux/mdss_rotator.h>
#include <poll.h>
#include <pthread.h>
diff --git a/displayengine/libs/core/fb/hw_hdmi.cpp b/displayengine/libs/core/fb/hw_hdmi.cpp
index 0a908bf..fec8661 100644
--- a/displayengine/libs/core/fb/hw_hdmi.cpp
+++ b/displayengine/libs/core/fb/hw_hdmi.cpp
@@ -105,7 +105,7 @@
}
HWHDMI::HWHDMI(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
- : HWDevice(buffer_sync_handler) {
+ : HWDevice(buffer_sync_handler), hw_scan_info_() {
HWDevice::device_type_ = kDeviceHDMI;
HWDevice::device_name_ = "HDMI Display Device";
HWDevice::hw_info_intf_ = hw_info_intf;
@@ -129,6 +129,7 @@
MSM_HDMI_MODES_INIT_TIMINGS(supported_video_modes_);
MSM_HDMI_MODES_SET_SUPP_TIMINGS(supported_video_modes_, MSM_HDMI_MODES_ALL);
+ ReadScanInfo();
return kErrorNone;
CleanupOnError:
@@ -340,5 +341,80 @@
return HWDevice::GetHWPanelInfo(panel_info);
}
+DisplayError HWHDMI::GetHWScanInfo(HWScanInfo *scan_info) {
+ if (!scan_info) {
+ return kErrorParameters;
+ }
+ *scan_info = hw_scan_info_;
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::GetVideoFormat(uint32_t config_index, uint32_t *video_format) {
+ *video_format = hdmi_modes_[config_index];
+
+ return kErrorNone;
+}
+
+DisplayError HWHDMI::GetMaxCEAFormat(uint32_t *max_cea_format) {
+ *max_cea_format = HDMI_VFRMT_END;
+
+ return kErrorNone;
+}
+
+HWScanSupport HWHDMI::MapHWScanSupport(uint32_t value) {
+ switch (value) {
+ // TODO(user): Read the scan type from driver defined values instead of hardcoding
+ case 0:
+ return kScanNotSupported;
+ case 1:
+ return kScanAlwaysOverscanned;
+ case 2:
+ return kScanAlwaysUnderscanned;
+ case 3:
+ return kScanBoth;
+ default:
+ return kScanNotSupported;
+ break;
+ }
+}
+
+void HWHDMI::ReadScanInfo() {
+ int scan_info_file = -1;
+ ssize_t len = -1;
+ char data[PAGE_SIZE] = {'\0'};
+
+ snprintf(data, sizeof(data), "%s%d/scan_info", fb_path_, fb_node_index_);
+ scan_info_file = open_(data, O_RDONLY);
+ if (scan_info_file < 0) {
+ DLOGW("File '%s' not found.", data);
+ return;
+ }
+
+ memset(&data[0], 0, sizeof(data));
+ len = read(scan_info_file, data, sizeof(data) - 1);
+ if (len <= 0) {
+ close_(scan_info_file);
+ DLOGW("File %s%d/scan_info is empty.", fb_path_, fb_node_index_);
+ return;
+ }
+ data[len] = '\0';
+ close_(scan_info_file);
+
+ const uint32_t scan_info_max_count = 3;
+ uint32_t scan_info_count = 0;
+ char *tokens[scan_info_max_count] = { NULL };
+ ParseLine(data, tokens, scan_info_max_count, &scan_info_count);
+ if (scan_info_count != scan_info_max_count) {
+ DLOGW("Failed to parse scan info string %s", data);
+ return;
+ }
+
+ hw_scan_info_.pt_scan_support = MapHWScanSupport(atoi(tokens[0]));
+ hw_scan_info_.it_scan_support = MapHWScanSupport(atoi(tokens[1]));
+ hw_scan_info_.cea_scan_support = MapHWScanSupport(atoi(tokens[2]));
+ DLOGI("PT %d IT %d CEA %d", hw_scan_info_.pt_scan_support, hw_scan_info_.it_scan_support,
+ hw_scan_info_.cea_scan_support);
+}
+
} // namespace sde
diff --git a/displayengine/libs/core/fb/hw_hdmi.h b/displayengine/libs/core/fb/hw_hdmi.h
index 322e664..adfa1e2 100644
--- a/displayengine/libs/core/fb/hw_hdmi.h
+++ b/displayengine/libs/core/fb/hw_hdmi.h
@@ -25,6 +25,7 @@
#ifndef __HW_HDMI_H__
#define __HW_HDMI_H__
+#include <video/msm_hdmi_modes.h>
#include "hw_device.h"
#include "hw_hdmi_interface.h"
@@ -41,6 +42,9 @@
virtual DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
uint32_t index);
virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
+ virtual DisplayError GetHWScanInfo(HWScanInfo *scan_info);
+ virtual DisplayError GetVideoFormat(uint32_t config_index, uint32_t *video_format);
+ virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format);
virtual DisplayError SetDisplayAttributes(uint32_t index);
virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
virtual DisplayError PowerOn();
@@ -54,11 +58,14 @@
private:
int GetHDMIModeCount();
+ void ReadScanInfo();
+ HWScanSupport MapHWScanSupport(uint32_t value);
uint32_t hdmi_mode_count_;
uint32_t hdmi_modes_[256];
// Holds the hdmi timing information. Ex: resolution, fps etc.,
msm_hdmi_mode_timing_info *supported_video_modes_;
+ HWScanInfo hw_scan_info_;
};
} // namespace sde
diff --git a/displayengine/libs/core/hw_hdmi_interface.h b/displayengine/libs/core/hw_hdmi_interface.h
index 36ca991..276fefd 100644
--- a/displayengine/libs/core/hw_hdmi_interface.h
+++ b/displayengine/libs/core/hw_hdmi_interface.h
@@ -36,6 +36,9 @@
static DisplayError Create(HWHDMIInterface **intf, HWInfoInterface *hw_info_intf,
BufferSyncHandler *buffer_sync_handler);
static DisplayError Destroy(HWHDMIInterface *intf);
+ virtual DisplayError GetHWScanInfo(HWScanInfo *scan_info) = 0;
+ virtual DisplayError GetVideoFormat(uint32_t config_index, uint32_t *video_format) = 0;
+ virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format) = 0;
protected:
virtual ~HWHDMIInterface() { }
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index 690bf30..7794731 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -390,6 +390,7 @@
hwc_rect_t scaled_display_frame = hwc_layer.displayFrame;
ScaleDisplayFrame(&scaled_display_frame);
+ ApplyScanAdjustment(&scaled_display_frame);
SetRect(scaled_display_frame, &layer.dst_rect);
SetRect(hwc_layer.sourceCropf, &layer.src_rect);
@@ -1000,5 +1001,8 @@
return fps;
}
+void HWCDisplay::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+}
+
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index 15aefd4..8a68619 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -115,6 +115,7 @@
void MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list);
void CloseAcquireFences(hwc_display_contents_1_t *content_list);
uint32_t RoundToStandardFPS(uint32_t fps);
+ virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
enum {
INPUT_LAYER_DUMP,
diff --git a/displayengine/libs/hwc/hwc_display_external.cpp b/displayengine/libs/hwc/hwc_display_external.cpp
index 2758e3a..9e57114 100644
--- a/displayengine/libs/hwc/hwc_display_external.cpp
+++ b/displayengine/libs/hwc/hwc_display_external.cpp
@@ -27,6 +27,7 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <cutils/properties.h>
#include <utils/constants.h>
#include "hwc_display_external.h"
@@ -40,6 +41,17 @@
: HWCDisplay(core_intf, hwc_procs, kHDMI, HWC_DISPLAY_EXTERNAL) {
}
+int HWCDisplayExternal::Init() {
+ int status = 0;
+
+ status = HWCDisplay::Init();
+ if (status != 0) {
+ return status;
+ }
+
+ return status;
+}
+
int HWCDisplayExternal::Prepare(hwc_display_contents_1_t *content_list) {
int status = 0;
@@ -91,5 +103,39 @@
return 0;
}
+void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+ if (display_intf_->IsUnderscanSupported()) {
+ return;
+ }
+
+ // Read user defined width and height ratio
+ char property[PROPERTY_VALUE_MAX];
+ property_get("persist.sys.actionsafe.width", property, "0");
+ float width_ratio = FLOAT(atoi(property)) / 100.0f;
+ property_get("persist.sys.actionsafe.height", property, "0");
+ float height_ratio = FLOAT(atoi(property)) / 100.0f;
+
+ if (width_ratio == 0.0f || height_ratio == 0.0f) {
+ return;
+ }
+
+ uint32_t panel_width = 0;
+ uint32_t panel_height = 0;
+ GetPanelResolution(&panel_width, &panel_height);
+
+ if (panel_width == 0 || panel_height == 0) {
+ DLOGV("Invalid panel dimensions (%d, %d)", panel_width, panel_height);
+ return;
+ }
+
+ int x_offset = INT((FLOAT(panel_width) * width_ratio) / 2.0f);
+ int y_offset = INT((FLOAT(panel_height) * height_ratio) / 2.0f);
+
+ display_frame->left = display_frame->left + x_offset;
+ display_frame->top = display_frame->top + y_offset;
+ display_frame->right = display_frame->right - x_offset;
+ display_frame->bottom = display_frame->bottom - y_offset;
+}
+
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_external.h b/displayengine/libs/hwc/hwc_display_external.h
index e268621..6795761 100644
--- a/displayengine/libs/hwc/hwc_display_external.h
+++ b/displayengine/libs/hwc/hwc_display_external.h
@@ -32,9 +32,12 @@
class HWCDisplayExternal : public HWCDisplay {
public:
explicit HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
+ virtual int Init();
virtual int Prepare(hwc_display_contents_1_t *content_list);
virtual int Commit(hwc_display_contents_1_t *content_list);
virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs);
+ private:
+ virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
};
} // namespace sde