From bee374610533f2766de31870026a557bb0fc6357 Mon Sep 17 00:00:00 2001 From: "Fan, Yugang" Date: Thu, 30 May 2019 00:51:42 +0800 Subject: [PATCH] Limits some monitors' modes due to hardware limitation. Defines HWC_LIMITED_MONITOR_LIST for limited monitors' name, and only exposes the preferred mode for those monitors. Tests: Works well with limited monitors (e.g. "TD2230 Series") and other normal monitor, and can get display name from debug log. limited monitor only exposes preferred mode to uplevel. Tracked-On: OAM-78920 Signed-off-by: Yugang Fan Change-Id: Ic8bf86c4ea7fdc98de48fb54da669172425afe0b --- wsi/drm/drmdisplay.cpp | 63 ++++++++++++++++++++++++++++++++++- wsi/drm/drmdisplay.h | 4 +++ wsi/drm/drmdisplaymanager.cpp | 18 ++++++++-- wsi/physicaldisplay.h | 10 ++++++ 4 files changed, 92 insertions(+), 3 deletions(-) diff --git a/wsi/drm/drmdisplay.cpp b/wsi/drm/drmdisplay.cpp index 5c034242..c314392a 100644 --- a/wsi/drm/drmdisplay.cpp +++ b/wsi/drm/drmdisplay.cpp @@ -154,6 +154,66 @@ void DrmDisplay::DrmConnectorGetDCIP3Support( return; } +void DrmDisplay::GetEDIDDisplayData(const ScopedDrmObjectPropertyPtr &props) { + uint8_t *edid = NULL; + uint64_t edid_blob_id; + struct edid_display_data display_data[4]; + drmModePropertyBlobPtr blob; + + GetDrmObjectPropertyValue("EDID", props, &edid_blob_id); + blob = drmModeGetPropertyBlob(gpu_fd_, edid_blob_id); + if (!blob) { + return; + } + + edid = (uint8_t *)blob->data; + if (!edid) { + return; + } + std::memset(display_data, 0, sizeof(display_data)); + std::memcpy((void *)display_data, (void *)(edid + 54), + sizeof(edid_display_data) * 4); + + for (int i = 0; i < 4; i++) { + if (!(display_data[i].indicate == 0x0000 && + display_data[i].reserved1 == 0x00 && + display_data[i].reserved2 == 0x00)) + continue; + + if (display_data[i].tag_number == 0xfc) { + display_name_.clear(); + size_t display_desc_size = + sizeof(((struct edid_display_data *)0)->desc_data); + size_t display_desc_str_size = + strchrnul((char *)display_data[i].desc_data, '\n') - + (char *)display_data[i].desc_data; + size_t display_desc_copy_size = display_desc_str_size > display_desc_size + ? display_desc_size + : display_desc_str_size; + display_name_.assign((char *)display_data[i].desc_data, + display_desc_copy_size); + } + } + + ITRACE("Got EDID display name \"%s\"\n", display_name_.c_str()); +} + +/* +* Check limited monitors exposing some modes which not +* be supported by monitor hardware actually. Limited monitors +* be defined in HWC_LIMITED_MONITOR_LIST. +*/ +bool DrmDisplay::CheckLimitedMonitor() { + for (unsigned int i = 0; i < HWC_LIMITED_MONITOR_LIST.size(); ++i) { + if (display_name_.compare(HWC_LIMITED_MONITOR_LIST[i]) == 0) { + ITRACE("Got a limited monitor: %s\n", + HWC_LIMITED_MONITOR_LIST[i].c_str()); + return true; + } + } + return false; +} + bool DrmDisplay::ConnectDisplay(const drmModeModeInfo &mode_info, const drmModeConnector *connector, uint32_t config) { @@ -231,6 +291,8 @@ bool DrmDisplay::ConnectDisplay(const drmModeModeInfo &mode_info, ITRACE("DCIP3 support not available"); } + GetEDIDDisplayData(connector_props); + PhysicalDisplay::Connect(); SetHDCPState(desired_protection_support_, content_type_); @@ -636,7 +698,6 @@ void DrmDisplay::SetDrmModeInfo(const std::vector &mode_info) { #endif modes_.emplace_back(mode_info[i]); } - SPIN_UNLOCK(display_lock_); } diff --git a/wsi/drm/drmdisplay.h b/wsi/drm/drmdisplay.h index e96e0923..415135ff 100644 --- a/wsi/drm/drmdisplay.h +++ b/wsi/drm/drmdisplay.h @@ -133,6 +133,8 @@ class DrmDisplay : public PhysicalDisplay { first_commit_ = true; } + bool CheckLimitedMonitor(); + private: void ShutDownPipe(); void GetDrmObjectPropertyValue(const char *name, @@ -165,6 +167,7 @@ class DrmDisplay : public PhysicalDisplay { std::vector FindExtendedBlocksForTag(uint8_t *edid, uint8_t block_tag); void DrmConnectorGetDCIP3Support(const ScopedDrmObjectPropertyPtr &props); + void GetEDIDDisplayData(const ScopedDrmObjectPropertyPtr &props); void TraceFirstCommit(); @@ -195,6 +198,7 @@ class DrmDisplay : public PhysicalDisplay { uint32_t flags_ = DRM_MODE_ATOMIC_ALLOW_MODESET; bool planes_updated_ = false; bool first_commit_ = false; + std::string display_name_; HWCContentProtection current_protection_support_ = HWCContentProtection::kUnSupported; HWCContentProtection desired_protection_support_ = diff --git a/wsi/drm/drmdisplaymanager.cpp b/wsi/drm/drmdisplaymanager.cpp index b21bf00f..6fd8154f 100644 --- a/wsi/drm/drmdisplaymanager.cpp +++ b/wsi/drm/drmdisplaymanager.cpp @@ -285,7 +285,14 @@ bool DrmDisplayManager::UpdateDisplayState() { encoder->crtc_id, display->CrtcId(), display->GetDisplayPipe()); // Set the modes supported for each display - display->SetDrmModeInfo(mode); + if (display->CheckLimitedMonitor()) { + // only expose the preferred mode for limited monitor + std::vector limited_mode( + 1, connector->modes[preferred_mode]); + display->SetDrmModeInfo(limited_mode); + } else { + display->SetDrmModeInfo(mode); + } break; } } @@ -330,7 +337,14 @@ bool DrmDisplayManager::UpdateDisplayState() { IHOTPLUGEVENTTRACE("Connected with crtc: %d pipe:%d \n", display->CrtcId(), display->GetDisplayPipe()); // Set the modes supported for each display - display->SetDrmModeInfo(mode); + if (display->CheckLimitedMonitor()) { + // only expose the preferred mode for limited monitor + std::vector limited_mode( + 1, connector->modes[preferred_mode]); + display->SetDrmModeInfo(limited_mode); + } else { + display->SetDrmModeInfo(mode); + } break; } } diff --git a/wsi/physicaldisplay.h b/wsi/physicaldisplay.h index 471f13ca..4fd91f7e 100644 --- a/wsi/physicaldisplay.h +++ b/wsi/physicaldisplay.h @@ -306,5 +306,15 @@ class PhysicalDisplay : public NativeDisplay, public DisplayPlaneHandler { uint32_t config_ = DEFAULT_CONFIG_ID; }; +struct __attribute__((packed)) edid_display_data { + uint16_t indicate; + uint8_t reserved1; + uint8_t tag_number; + uint8_t reserved2; + uint8_t desc_data[13]; +}; + +const std::vector HWC_LIMITED_MONITOR_LIST{"TD2230 Series"}; + } // namespace hwcomposer #endif // WSI_PHYSICALDISPLAY_H_