diff options
Diffstat (limited to 'libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp')
-rw-r--r-- | libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp | 240 |
1 files changed, 179 insertions, 61 deletions
diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp index e8a4001..badaa61 100644 --- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp +++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp @@ -40,7 +40,6 @@ using namespace SOC_VERSION; constexpr uint32_t MAX_PLANE_NUM = 3; constexpr uint32_t CBCR_INDEX = 1; constexpr float DISPLAY_LUMINANCE_UNIT = 10000; -constexpr auto nsecsPerSec = std::chrono::nanoseconds(1s).count(); constexpr auto vsyncPeriodTag = "VsyncPeriod"; typedef struct _drmModeAtomicReqItem drmModeAtomicReqItem, *drmModeAtomicReqItemPtr; @@ -62,6 +61,19 @@ using namespace vendor::graphics; extern struct exynos_hwc_control exynosHWCControl; static const int32_t kUmPerInch = 25400; +int writeIntToKernelFile(const char* path, const int value) { + std::ofstream ofs(path); + + if (!ofs.is_open()) { + ALOGW("%s(): unable to open %s (%s)", __func__, path, strerror(errno)); + return -1; + } + + ofs << value << std::endl; + + return 0; +} + FramebufferManager::~FramebufferManager() { { @@ -449,6 +461,16 @@ void ExynosDisplayDrmInterface::destroyLayer(ExynosLayer *layer) { } int32_t ExynosDisplayDrmInterface::getDisplayIdleTimerSupport(bool &outSupport) { + if (isFullVrrSupported()) { + outSupport = false; + return NO_ERROR; + } else if (isPseudoVrrSupported()) { + // Retuen true to avoid SF idle timer working. We insert frames manually + // for pseudo VRR, so ideally panel idle should be disabled in the driver. + outSupport = true; + return NO_ERROR; + } + auto [ret, support] = mDrmConnector->panel_idle_support().value(); if (ret) { ALOGI("no panel_idle_support drm property or invalid value (%d)", ret); @@ -628,7 +650,7 @@ void ExynosDisplayDrmInterface::updateMountOrientation() for (auto &e : orientationEnums) { uint64_t enumValue; - std::tie(enumValue, err) = orientation.GetEnumValueWithName(e.second); + std::tie(enumValue, err) = orientation.getEnumValueWithName(e.second); if (!err && enumValue == drmOrientation) { mExynosDisplay->mMountOrientation = e.first; return; @@ -723,7 +745,7 @@ int32_t ExynosDisplayDrmInterface::initDrmDevice(DrmDevice *drmDevice) auto &plane = mDrmDevice->planes().at(i); uint32_t plane_id = plane->id(); - if (!plane->zpos_property().is_immutable()) { + if (!plane->zpos_property().isImmutable()) { /* Plane can be used for composition */ ExynosMPP *exynosMPP = mExynosDisplay->mResourceManager->getOtfMPPWithChannel(i); @@ -760,10 +782,10 @@ int32_t ExynosDisplayDrmInterface::initDrmDevice(DrmDevice *drmDevice) parseRangeEnums(plane->range_property()); } - chosePreferredConfig(); + choosePreferredConfig(); - // After chosePreferredConfig, the mDrmConnector->modes array is initialized, get the panel full - // resolution information here. + // After choosePreferredConfig, the mDrmConnector->modes array is initialized, get the panel + // full resolution information here. if (mExynosDisplay->mType == HWC_DISPLAY_PRIMARY) { retrievePanelFullResolution(); } @@ -841,6 +863,8 @@ void ExynosDisplayDrmInterface::Callback( mExynosDisplay->mLastVsyncTimestamp = timestamp; } + mExynosDisplay->onVsync(timestamp); + ExynosDevice *exynosDevice = mExynosDisplay->mDevice; if (exynosDevice->onVsync_2_4(mExynosDisplay->mDisplayId, timestamp, @@ -902,12 +926,14 @@ int32_t ExynosDisplayDrmInterface::setLowPowerMode() { mExynosDisplay->mXres = mDozeDrmMode.h_display(); mExynosDisplay->mYres = mDozeDrmMode.v_display(); // in nanoseconds - mExynosDisplay->mVsyncPeriod = nsecsPerSec / mDozeDrmMode.v_refresh(); + mExynosDisplay->mVsyncPeriod = static_cast<uint32_t>(mDozeDrmMode.te_period()); // Dots per 1000 inches mExynosDisplay->mXdpi = mm_width ? (mDozeDrmMode.h_display() * kUmPerInch) / mm_width : -1; // Dots per 1000 inches mExynosDisplay->mYdpi = mm_height ? (mDozeDrmMode.v_display() * kUmPerInch) / mm_height : -1; + mExynosDisplay->mRefreshRate = static_cast<int32_t>(mDozeDrmMode.v_refresh()); + return setActiveDrmMode(mDozeDrmMode); } @@ -949,8 +975,7 @@ int32_t ExynosDisplayDrmInterface::setVsyncEnabled(uint32_t enabled) return NO_ERROR; } -int32_t ExynosDisplayDrmInterface::chosePreferredConfig() -{ +int32_t ExynosDisplayDrmInterface::choosePreferredConfig() { uint32_t num_configs = 0; int32_t err = getDisplayConfigs(&num_configs, NULL); if (err != HWC2_ERROR_NONE || !num_configs) @@ -959,9 +984,10 @@ int32_t ExynosDisplayDrmInterface::chosePreferredConfig() int32_t config = -1; char modeStr[PROPERTY_VALUE_MAX] = "\0"; int32_t width = 0, height = 0, fps = 0; + // only legacy products use this property, kernel preferred mode will be used going forward if (property_get("vendor.display.preferred_mode", modeStr, "") > 0 && sscanf(modeStr, "%dx%d@%d", &width, &height, &fps) == 3) { - err = mExynosDisplay->lookupDisplayConfigs(width, height, fps, &config); + err = mExynosDisplay->lookupDisplayConfigs(width, height, fps, fps, &config); } else { err = HWC2_ERROR_BAD_CONFIG; } @@ -997,19 +1023,25 @@ int32_t ExynosDisplayDrmInterface::getDisplayConfigs( uint32_t* outNumConfigs, hwc2_config_t* outConfigs) { + if (!mExynosDisplay || !(mExynosDisplay->mDevice)) { + return HWC2_ERROR_BAD_DISPLAY; + } + std::lock_guard<std::recursive_mutex> lock(mDrmConnector->modesLock()); if (!outConfigs) { - int ret = mDrmConnector->UpdateModes(); + bool useVrrConfigs = isFullVrrSupported(); + int ret = mDrmConnector->UpdateModes(useVrrConfigs); if (ret < 0) { ALOGE("Failed to update display modes %d", ret); return HWC2_ERROR_BAD_DISPLAY; } - if (ret == 0) { // no need to update mExynosDisplay->mDisplayConfigs goto no_mode_changes; } + ALOGI("Select Vrr Config for display %s: %s", mExynosDisplay->mDisplayName.c_str(), + useVrrConfigs ? "full" : (isPseudoVrrSupported() ? "pseudo" : "non-Vrr")); if (mDrmConnector->state() == DRM_MODE_CONNECTED) { /* @@ -1030,28 +1062,23 @@ int32_t ExynosDisplayDrmInterface::getDisplayConfigs( uint32_t mm_width = mDrmConnector->mm_width(); uint32_t mm_height = mDrmConnector->mm_height(); + ALOGD("%s: mm_width(%u) mm_height(%u)", + mExynosDisplay->mDisplayName.c_str(), mm_width, mm_height); - /* key: (width<<32 | height) */ - std::map<uint64_t, uint32_t> groupIds; - uint32_t groupId = 0; + DisplayConfigGroupIdGenerator groupIdGenerator; float peakRr = -1; - for (const DrmMode &mode : mDrmConnector->modes()) { displayConfigs_t configs; float rr = mode.v_refresh(); - configs.vsyncPeriod = nsecsPerSec / rr; + configs.refreshRate = static_cast<int32_t>(rr); + configs.vsyncPeriod = static_cast<int32_t>(mode.te_period()); + if (configs.vsyncPeriod <= 0.0f) { + ALOGE("%s:: invalid vsync period", __func__); + return HWC2_ERROR_BAD_DISPLAY; + } + configs.isOperationRateToBts = mode.is_operation_rate_to_bts(); configs.width = mode.h_display(); configs.height = mode.v_display(); - uint64_t key = ((uint64_t)configs.width<<32) | configs.height; - auto it = groupIds.find(key); - if (it != groupIds.end()) { - configs.groupId = it->second; - } else { - configs.groupId = groupId; - groupIds.insert(std::make_pair(key, groupId)); - groupId++; - } - // Dots per 1000 inches configs.Xdpi = mm_width ? (mode.h_display() * kUmPerInch) / mm_width : -1; // Dots per 1000 inches @@ -1059,10 +1086,29 @@ int32_t ExynosDisplayDrmInterface::getDisplayConfigs( // find peak rr if (rr > peakRr) peakRr = rr; + // Configure VRR if it's turned on. + if (mode.is_vrr_mode()) { + VrrConfig_t vrrConfig; + vrrConfig.minFrameIntervalNs = static_cast<int>(std::nano::den / rr); + // TODO(b/290843234): FrameIntervalPowerHint is currently optional and omitted. + // Supply initial values for notifyExpectedPresentConfig; potential changes may come + // later. + vrrConfig.notifyExpectedPresentConfig.HeadsUpNs = mNotifyExpectedPresentHeadsUpNs; + vrrConfig.notifyExpectedPresentConfig.TimeoutNs = mNotifyExpectedPresentTimeoutNs; + configs.vrrConfig = std::make_optional(vrrConfig); + configs.groupId = groupIdGenerator.getGroupId(configs.width, configs.height, + vrrConfig.minFrameIntervalNs, + configs.vsyncPeriod); + } else { + configs.groupId = groupIdGenerator.getGroupId(configs.width, configs.height); + } mExynosDisplay->mDisplayConfigs.insert(std::make_pair(mode.id(), configs)); - ALOGD("config group(%d), w(%d), h(%d), vsync(%d), xdpi(%d), ydpi(%d)", - configs.groupId, configs.width, configs.height, - configs.vsyncPeriod, configs.Xdpi, configs.Ydpi); + ALOGD("%s: config group(%d), w(%d), h(%d), rr(%f), TE(%d), xdpi(%d), ydpi(%d), " + "vrr mode(%s), NS mode(%s)", + mExynosDisplay->mDisplayName.c_str(), + configs.groupId, configs.width, configs.height, rr, configs.vsyncPeriod, + configs.Xdpi, configs.Ydpi, mode.is_vrr_mode() ? "true" : "false", + mode.is_ns_mode() ? "true" : "false"); } mExynosDisplay->setPeakRefreshRate(peakRr); } @@ -1093,13 +1139,16 @@ void ExynosDisplayDrmInterface::dumpDisplayConfigs() uint32_t num_modes = static_cast<uint32_t>(mDrmConnector->modes().size()); for (uint32_t i = 0; i < num_modes; i++) { auto mode = mDrmConnector->modes().at(i); - ALOGD("%s display config[%d] %s:: id(%d), clock(%d), flags(%d), type(%d)", - mExynosDisplay->mDisplayName.c_str(), i, mode.name().c_str(), mode.id(), mode.clock(), mode.flags(), mode.type()); + ALOGD("%s: config[%d] %s: id(%d), clock(%d), flags(0x%x), type(0x%x)", + mExynosDisplay->mDisplayName.c_str(), i, mode.name().c_str(), mode.id(), + mode.clock(), mode.flags(), mode.type()); ALOGD("\th_display(%d), h_sync_start(%d), h_sync_end(%d), h_total(%d), h_skew(%d)", - mode.h_display(), mode.h_sync_start(), mode.h_sync_end(), mode.h_total(), mode.h_skew()); - ALOGD("\tv_display(%d), v_sync_start(%d), v_sync_end(%d), v_total(%d), v_scan(%d), v_refresh(%f)", - mode.v_display(), mode.v_sync_start(), mode.v_sync_end(), mode.v_total(), mode.v_scan(), mode.v_refresh()); - + mode.h_display(), mode.h_sync_start(), mode.h_sync_end(), mode.h_total(), + mode.h_skew()); + ALOGD("\tv_display(%d), v_sync_start(%d), v_sync_end(%d), v_total(%d), v_scan(%d), " + "v_refresh(%f)", + mode.v_display(), mode.v_sync_start(), mode.v_sync_end(), mode.v_total(), + mode.v_scan(), mode.v_refresh()); } } @@ -1110,7 +1159,7 @@ int32_t ExynosDisplayDrmInterface::getDisplayVsyncPeriod(hwc2_vsync_period_t* ou int32_t ExynosDisplayDrmInterface::getConfigChangeDuration() { - const auto [ret, duration] = mDrmConnector->vrr_switch_duration().value(); + const auto [ret, duration] = mDrmConnector->rr_switch_duration().value(); if (!ret && duration > 0) { return duration; @@ -1248,7 +1297,7 @@ int32_t ExynosDisplayDrmInterface::setActiveConfigWithConstraints( } else if ((mActiveModeState.blob_id != 0) && (mActiveModeState.mode.id() == config)) { ALOGD("%s:: same mode %d", __func__, config); /* trigger resetConfigRequestStateLocked() */ - mVsyncCallback.setDesiredVsyncPeriod(nsecsPerSec / mActiveModeState.mode.v_refresh()); + mVsyncCallback.setDesiredVsyncPeriod(mActiveModeState.mode.te_period()); mDrmVSyncWorker.VSyncControl(true); return HWC2_ERROR_NONE; } @@ -1279,7 +1328,8 @@ int32_t ExynosDisplayDrmInterface::setActiveConfigWithConstraints( } } else { if (!isResSwitch) { - ret = setDisplayMode(drmReq, modeBlob ? modeBlob : mDesiredModeState.blob_id); + ret = setDisplayMode(drmReq, modeBlob ? modeBlob : mDesiredModeState.blob_id, + modeBlob ? mode->id() : mDesiredModeState.mode.id()); if (ret < 0) { HWC_LOGE(mExynosDisplay, "%s: Fail to apply display mode", __func__); return ret; @@ -1325,7 +1375,7 @@ int32_t ExynosDisplayDrmInterface::setActiveDrmMode(DrmMode const &mode) { reconfig = true; } - if ((ret = setDisplayMode(drmReq, modeBlob)) != NO_ERROR) { + if ((ret = setDisplayMode(drmReq, modeBlob, mode.id())) != NO_ERROR) { drmReq.addOldBlob(modeBlob); HWC_LOGE(mExynosDisplay, "%s: Fail to apply display mode", __func__); @@ -1394,9 +1444,9 @@ int32_t ExynosDisplayDrmInterface::createModeBlob(const DrmMode &mode, return NO_ERROR; } -int32_t ExynosDisplayDrmInterface::setDisplayMode( - DrmModeAtomicReq &drmReq, const uint32_t modeBlob) -{ +int32_t ExynosDisplayDrmInterface::setDisplayMode(DrmModeAtomicReq& drmReq, + const uint32_t& modeBlob, + const uint32_t& modeId) { int ret = NO_ERROR; if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(), @@ -1411,6 +1461,10 @@ int32_t ExynosDisplayDrmInterface::setDisplayMode( mDrmConnector->crtc_id_property(), mDrmCrtc->id())) < 0) return ret; + if (mConfigChangeCallback) { + drmReq.setAckCallback(std::bind(mConfigChangeCallback, modeId)); + } + return NO_ERROR; } @@ -1427,6 +1481,10 @@ int32_t ExynosDisplayDrmInterface::updateHdrCapabilities() mExynosDisplay->mMaxAverageLuminance = 0; mExynosDisplay->mMinLuminance = 0; + if (mExynosDisplay->mType == HWC_DISPLAY_EXTERNAL) { + int upd_res = mDrmConnector->UpdateLuminanceAndHdrProperties(); + if (!upd_res) ALOGW("%s: UpdateLuminanceAndHdrProperties failed (%d)", __func__, upd_res); + } const DrmProperty &prop_max_luminance = mDrmConnector->max_luminance(); const DrmProperty &prop_max_avg_luminance = mDrmConnector->max_avg_luminance(); const DrmProperty &prop_min_luminance = mDrmConnector->min_luminance(); @@ -1442,9 +1500,11 @@ int32_t ExynosDisplayDrmInterface::updateHdrCapabilities() (prop_max_avg_luminance.id() == 0) || (prop_min_luminance.id() == 0) || (prop_hdr_formats.id() == 0)) { - ALOGE("%s:: there is no property for hdrCapabilities (max_luminance: %d, max_avg_luminance: %d, min_luminance: %d, hdr_formats: %d", - __func__, prop_max_luminance.id(), prop_max_avg_luminance.id(), - prop_min_luminance.id(), prop_hdr_formats.id()); + HWC_LOGE(mExynosDisplay, + "%s:: there is no property for hdrCapabilities (max_luminance: %d, " + "max_avg_luminance: %d, min_luminance: %d, hdr_formats: %d", + __func__, prop_max_luminance.id(), prop_max_avg_luminance.id(), + prop_min_luminance.id(), prop_hdr_formats.id()); return -1; } @@ -1480,13 +1540,13 @@ int32_t ExynosDisplayDrmInterface::updateHdrCapabilities() } uint32_t typeBit; - std::tie(typeBit, ret) = prop_hdr_formats.GetEnumValueWithName("Dolby Vision"); + std::tie(typeBit, ret) = prop_hdr_formats.getEnumValueWithName("Dolby Vision"); if ((ret == 0) && (hdr_formats & (1 << typeBit))) { mExynosDisplay->mHdrTypes.push_back(HAL_HDR_DOLBY_VISION); HDEBUGLOGD(eDebugHWC, "%s: supported hdr types : %d", mExynosDisplay->mDisplayName.c_str(), HAL_HDR_DOLBY_VISION); } - std::tie(typeBit, ret) = prop_hdr_formats.GetEnumValueWithName("HDR10"); + std::tie(typeBit, ret) = prop_hdr_formats.getEnumValueWithName("HDR10"); if ((ret == 0) && (hdr_formats & (1 << typeBit))) { mExynosDisplay->mHdrTypes.push_back(HAL_HDR_HDR10); if (mExynosDisplay->mDevice->mResourceManager->hasHDR10PlusMPP()) { @@ -1495,7 +1555,7 @@ int32_t ExynosDisplayDrmInterface::updateHdrCapabilities() HDEBUGLOGD(eDebugHWC, "%s: supported hdr types : %d", mExynosDisplay->mDisplayName.c_str(), HAL_HDR_HDR10); } - std::tie(typeBit, ret) = prop_hdr_formats.GetEnumValueWithName("HLG"); + std::tie(typeBit, ret) = prop_hdr_formats.getEnumValueWithName("HLG"); if ((ret == 0) && (hdr_formats & (1 << typeBit))) { mExynosDisplay->mHdrTypes.push_back(HAL_HDR_HLG); HDEBUGLOGD(eDebugHWC, "%s: supported hdr types : %d", @@ -1591,12 +1651,11 @@ int32_t ExynosDisplayDrmInterface::setupCommitFromDisplayConfig( plane->blend_property(), drmEnum, true)) < 0) return ret; - if (plane->zpos_property().id() && - !plane->zpos_property().is_immutable()) { + if (plane->zpos_property().id() && !plane->zpos_property().isImmutable()) { uint64_t min_zpos = 0; // Ignore ret and use min_zpos as 0 by default - std::tie(std::ignore, min_zpos) = plane->zpos_property().range_min(); + std::tie(std::ignore, min_zpos) = plane->zpos_property().rangeMin(); if ((ret = drmReq.atomicAddProperty(plane->id(), plane->zpos_property(), configIndex + min_zpos)) < 0) @@ -1606,8 +1665,8 @@ int32_t ExynosDisplayDrmInterface::setupCommitFromDisplayConfig( if (plane->alpha_property().id()) { uint64_t min_alpha = 0; uint64_t max_alpha = 0; - std::tie(std::ignore, min_alpha) = plane->alpha_property().range_min(); - std::tie(std::ignore, max_alpha) = plane->alpha_property().range_max(); + std::tie(std::ignore, min_alpha) = plane->alpha_property().rangeMin(); + std::tie(std::ignore, max_alpha) = plane->alpha_property().rangeMax(); if ((ret = drmReq.atomicAddProperty(plane->id(), plane->alpha_property(), (uint64_t)(((max_alpha - min_alpha) * config.plane_alpha) + 0.5) + min_alpha, true)) < 0) @@ -1855,7 +1914,8 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData() 1 << mMipiSyncEnums[toUnderlying(HalMipiSyncType::HAL_MIPI_CMD_SYNC_REFRESH_RATE)]; } - if ((ret = setDisplayMode(drmReq, mDesiredModeState.blob_id)) < 0) { + if ((ret = setDisplayMode(drmReq, mDesiredModeState.blob_id, mDesiredModeState.mode.id())) < + 0) { HWC_LOGE(mExynosDisplay, "%s: Fail to apply display mode", __func__); return ret; @@ -2091,8 +2151,7 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData() mDrmConnector->ResetLpMode(); getLowPowerDrmModeModeInfo(); } - mVsyncCallback.setDesiredVsyncPeriod( - nsecsPerSec/mActiveModeState.mode.v_refresh()); + mVsyncCallback.setDesiredVsyncPeriod(mActiveModeState.mode.te_period()); /* Enable vsync to check vsync period */ mDrmVSyncWorker.VSyncControl(true); } @@ -2139,6 +2198,15 @@ int32_t ExynosDisplayDrmInterface::triggerClearDisplayPlanes() return ret; } +void ExynosDisplayDrmInterface::setVrrSettings(const VrrSettings_t& vrrSettings) { + if (vrrSettings.enabled) { + mIsVrrModeSupported = true; + mNotifyExpectedPresentHeadsUpNs = vrrSettings.notifyExpectedPresentConfig.HeadsUpNs; + mNotifyExpectedPresentTimeoutNs = vrrSettings.notifyExpectedPresentConfig.TimeoutNs; + mConfigChangeCallback = vrrSettings.configChangeCallback; + } +} + int32_t ExynosDisplayDrmInterface::clearDisplayPlanes(DrmModeAtomicReq &drmReq) { int ret = NO_ERROR; @@ -2292,7 +2360,7 @@ int32_t ExynosDisplayDrmInterface::DrmModeAtomicReq::atomicAddProperty( return -EINVAL; } - if (property.id()) { + if (property.id() && property.validateChange(value)) { int ret = drmModeAtomicAddProperty(mPset, id, property.id(), value); if (ret < 0) { @@ -2401,13 +2469,46 @@ int ExynosDisplayDrmInterface::DrmModeAtomicReq::commit(uint32_t flags, bool log ALOGV("skip atomic commit error handling as kernel is in TUI"); ret = NO_ERROR; } else if (ret < 0) { + if (ret == -EINVAL) { + dumpDrmAtomicCommitMessage(ret); + } HWC_LOGE(mDrmDisplayInterface->mExynosDisplay, "commit error: %d", ret); setError(ret); } + if (ret == 0 && mAckCallback) { + if (!(flags & DRM_MODE_ATOMIC_TEST_ONLY)) { + mAckCallback(); + } + } + return ret; } +void ExynosDisplayDrmInterface::DrmModeAtomicReq::dumpDrmAtomicCommitMessage(int err) { + const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + const nsecs_t diffMs = ns2ms(now - mDrmDisplayInterface->mLastDumpDrmAtomicMessageTime); + if (diffMs < kAllowDumpDrmAtomicMessageTimeMs) { + return; + } + + if (writeIntToKernelFile(kDrmModuleParametersDebugNode, kEnableDrmAtomicMessage)) { + return; + } + + HWC_LOGE(mDrmDisplayInterface->mExynosDisplay, + "commit error, enable atomic message and test again"); + int ret = drmModeAtomicCommit(mDrmDisplayInterface->mDrmDevice->fd(), mPset, + DRM_MODE_ATOMIC_TEST_ONLY, mDrmDisplayInterface->mDrmDevice); + if (ret != err) { + HWC_LOGE(mDrmDisplayInterface->mExynosDisplay, + "re-try commit error(%d) is different from %d", ret, err); + } + + writeIntToKernelFile(kDrmModuleParametersDebugNode, kDisableDrmDebugMessage); + mDrmDisplayInterface->mLastDumpDrmAtomicMessageTime = systemTime(SYSTEM_TIME_MONOTONIC); +} + int32_t ExynosDisplayDrmInterface::getReadbackBufferAttributes( int32_t* /*android_pixel_format_t*/ outFormat, int32_t* /*android_dataspace_t*/ outDataspace) @@ -2559,9 +2660,9 @@ void ExynosDisplayDrmInterface::DrmReadbackInfo::pickFormatDataspace() int32_t ExynosDisplayDrmInterface::getDisplayFakeEdid(uint8_t &outPort, uint32_t &outDataSize, uint8_t *outData) { - int width = mExynosDisplay->mXres; - int height = mExynosDisplay->mYres; - int clock = (width) * (height) * 60 / 10000; + uint32_t width = mExynosDisplay->mXres; + uint32_t height = mExynosDisplay->mYres; + uint32_t clock = (width * height * kDefaultRefreshRateFrequency) / 10000; std::array<uint8_t, 128> edid_buf{ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, /* header */ 0x1C, 0xEC, /* manufacturer GGL */ @@ -2771,3 +2872,20 @@ int32_t ExynosDisplayDrmInterface::sendHistogramChannelIoctl(HistogramChannelIoc ALOGE("%s: kernel doesn't support multi channel histogram ioctl", __func__); return INVALID_OPERATION; } + +static constexpr auto kDpHotplugErrorCodeSysfsPath = + "/sys/devices/platform/110f0000.drmdp/drm-displayport/dp_hotplug_error_code"; + +int ExynosDisplayDrmInterface::readHotplugErrorCode() { + if (mExynosDisplay->mType != HWC_DISPLAY_EXTERNAL) return 0; + int hotplug_error_code = 0; + std::ifstream ifs(kDpHotplugErrorCodeSysfsPath); + if (ifs.is_open()) ifs >> hotplug_error_code; + return hotplug_error_code; +} + +void ExynosDisplayDrmInterface::resetHotplugErrorCode() { + if (mExynosDisplay->mType != HWC_DISPLAY_EXTERNAL) return; + std::ofstream ofs(kDpHotplugErrorCodeSysfsPath); + if (ofs.is_open()) ofs << "0"; +} |