1 /*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 //#define LOG_NDEBUG 0
17
18 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
19
20 #include "ExynosPrimaryDisplay.h"
21
22 #include <android-base/properties.h>
23
24 #include <linux/fb.h>
25 #include <poll.h>
26
27 #include <chrono>
28 #include <fstream>
29
30 #include "../libvrr/FileNode.h"
31 #include "../libvrr/VariableRefreshRateVersion.h"
32 #include "../libvrr/interface/Panel_def.h"
33 #include "BrightnessController.h"
34 #include "DisplayTe2Manager.h"
35 #include "ExynosDevice.h"
36 #include "ExynosDisplayDrmInterface.h"
37 #include "ExynosDisplayDrmInterfaceModule.h"
38 #include "ExynosExternalDisplay.h"
39 #include "ExynosHWCDebug.h"
40 #include "ExynosHWCHelper.h"
41 #include "ExynosLayer.h"
42 #include "HistogramController.h"
43
44 extern struct exynos_hwc_control exynosHWCControl;
45
46 using namespace SOC_VERSION;
47
48 namespace {
49
50 using android::hardware::graphics::composer::kPanelRefreshCtrlFrameInsertionAutoMode;
51 using android::hardware::graphics::composer::kPanelRefreshCtrlFrameInsertionAutoModeOffset;
52 using android::hardware::graphics::composer::kPanelRefreshCtrlMrrV1OverV2;
53 using android::hardware::graphics::composer::kPanelRefreshCtrlMrrV1OverV2Offset;
54 using android::hardware::graphics::composer::kRefreshControlNodeEnabled;
55 using android::hardware::graphics::composer::kRefreshControlNodeName;
56
57 constexpr auto nsecsPerSec = std::chrono::nanoseconds(1s).count();
58
59 inline constexpr int kDefaultNotifyExpectedPresentConfigHeadsUpNs =
60 std::chrono::nanoseconds(30ms).count();
61 inline constexpr int kDefaultNotifyExpectedPresentConfigTimeoutNs =
62 std::chrono::nanoseconds(30ms).count();
63
64 static constexpr int kMaximumPropertyIdentifierLength = 128;
65
66 static const std::map<const DisplayType, const std::string> panelSysfsPath =
67 {{DisplayType::DISPLAY_PRIMARY, "/sys/devices/platform/exynos-drm/primary-panel/"},
68 #ifdef USES_IDISPLAY_INTF_SEC
69 {DisplayType::DISPLAY_SECONDARY, "/sys/devices/platform/exynos-drm/secondary-panel/"}
70 #endif
71
72 };
73 } // namespace
74
getPropertyBootModeStr(const int32_t dispId)75 static String8 getPropertyBootModeStr(const int32_t dispId) {
76 String8 str;
77 if (dispId == 0) {
78 str.appendFormat("persist.vendor.display.primary.boot_config");
79 } else {
80 str.appendFormat("persist.vendor.display.%d.primary.boot_config", dispId);
81 }
82 return str;
83 }
84
loadPanelGammaCalibration(const std::string & file)85 static std::string loadPanelGammaCalibration(const std::string &file) {
86 std::ifstream ifs(file);
87
88 if (!ifs.is_open()) {
89 ALOGW("Unable to open gamma calibration '%s', error = %s", file.c_str(), strerror(errno));
90 return {};
91 }
92
93 std::string raw_data, gamma;
94 char ch;
95 while (std::getline(ifs, raw_data, '\r')) {
96 gamma.append(raw_data);
97 gamma.append(1, ' ');
98 ifs.get(ch);
99 if (ch != '\n') {
100 gamma.append(1, ch);
101 }
102 }
103 ifs.close();
104
105 /* eliminate space character in the last byte */
106 if (!gamma.empty()) {
107 gamma.pop_back();
108 }
109
110 return gamma;
111 }
112
ExynosPrimaryDisplay(uint32_t index,ExynosDevice * device,const std::string & displayName)113 ExynosPrimaryDisplay::ExynosPrimaryDisplay(uint32_t index, ExynosDevice* device,
114 const std::string& displayName)
115 : ExynosDisplay(HWC_DISPLAY_PRIMARY, index, device, displayName),
116 mMinIdleRefreshRate(0),
117 mRrThrottleFps{0},
118 mRrThrottleNanos{0},
119 mRefreshRateDelayNanos(0),
120 mLastRefreshRateAppliedNanos(0),
121 mAppliedActiveConfig(0),
122 mDisplayIdleTimerEnabled(false),
123 mDisplayIdleTimerNanos{0},
124 mDisplayIdleDelayNanos(-1),
125 mDisplayNeedHandleIdleExit(false) {
126 // TODO : Hard coded here
127 mNumMaxPriorityAllowed = 5;
128
129 /* Initialization */
130 mFramesToReachLhbmPeakBrightness =
131 property_get_int32("vendor.primarydisplay.lhbm.frames_to_reach_peak_brightness", 3);
132
133 DisplayType displayType = getDcDisplayType();
134 std::string displayTypeIdentifier;
135 if (displayType == DisplayType::DISPLAY_PRIMARY) {
136 displayTypeIdentifier = "primarydisplay";
137 } else if (displayType == DisplayType::DISPLAY_EXTERNAL) {
138 displayTypeIdentifier = "externaldisplay";
139 }
140 #ifdef USES_IDISPLAY_INTF_SEC
141 else if (displayType == DisplayType::DISPLAY_SECONDARY) {
142 displayTypeIdentifier = "secondarydisplay";
143 }
144 #endif
145 if (!displayTypeIdentifier.empty()) {
146 // Blocking zone
147 auto propertyName =
148 "ro.vendor." + displayTypeIdentifier + ".blocking_zone.min_refresh_rate_by_nits";
149 auto minRefreshRateByBrightnessString = android::base::GetProperty(propertyName, "");
150 ALOGD("%s brightness blocking zone propterty = %s", __func__,
151 minRefreshRateByBrightnessString.c_str());
152 if (!minRefreshRateByBrightnessString.empty()) {
153 std::vector<std::string> patterns;
154 size_t pos = 0;
155 while ((pos = minRefreshRateByBrightnessString.find(',')) != std::string::npos) {
156 patterns.emplace_back(minRefreshRateByBrightnessString.substr(0, pos));
157 minRefreshRateByBrightnessString.erase(0, pos + 1);
158 }
159 patterns.emplace_back(minRefreshRateByBrightnessString);
160 std::string brightnessString, fpsString;
161 for (auto& pattern : patterns) {
162 int brightness, fps;
163 char* endPos;
164 pos = pattern.find(':');
165 if (pos == std::string::npos) {
166 ALOGE("%s(): cannot find the delimiter ':' of the pattern {brightness}:{fps} "
167 "in "
168 "pattern = %s",
169 __func__, pattern.c_str());
170 break;
171 } else {
172 brightnessString = pattern.substr(0, pos);
173 pattern.erase(0, pos + 1);
174 if (pattern.empty()) {
175 ALOGE("%s(): miss the {fps} of the pattern = %s", __func__,
176 pattern.c_str());
177 break;
178 } else {
179 fpsString = pattern;
180 }
181 brightness = brightnessString.empty()
182 ? INT_MAX
183 : std::strtol(brightnessString.c_str(), &endPos, 10);
184 fps = std::strtol(fpsString.c_str(), &endPos, 10);
185 }
186 mBrightnessBlockingZonesLookupTable[brightness] = fps;
187 }
188 ALOGI("Brightness blocking zone lookup table:");
189 int upperBound;
190 int lowerBound = INT_MIN;
191 for (const auto& brightnessBlockingZone : mBrightnessBlockingZonesLookupTable) {
192 upperBound = brightnessBlockingZone.first;
193 ALOGI("Brightness blocking zone: range [%s %s) fps = %d",
194 (lowerBound == INT_MIN ? "Min" : std::to_string(lowerBound).c_str()),
195 (upperBound == INT_MAX ? "Max" : std::to_string(upperBound).c_str()),
196 brightnessBlockingZone.second);
197 lowerBound = upperBound;
198 }
199 }
200 // XRR version
201 auto xrrVersion =
202 android::hardware::graphics::composer::getDisplayXrrVersion(displayTypeIdentifier);
203 mXrrSettings.versionInfo.majorVersion = xrrVersion.first;
204 mXrrSettings.versionInfo.minorVersion = xrrVersion.second;
205 ALOGI("%s() xRR version = %d.%d", __func__, mXrrSettings.versionInfo.majorVersion,
206 mXrrSettings.versionInfo.minorVersion);
207
208 uint32_t refreshControlCommand = 0;
209 if (mXrrSettings.versionInfo.needVrrParameters()) {
210 char pathBuffer[PROP_VALUE_MAX] = {0};
211 sprintf(pathBuffer, "ro.vendor.%s.vrr.expected_present.headsup_ns",
212 displayTypeIdentifier.c_str());
213 mXrrSettings.notifyExpectedPresentConfig.HeadsUpNs =
214 property_get_int32(pathBuffer, kDefaultNotifyExpectedPresentConfigHeadsUpNs);
215 sprintf(pathBuffer, "ro.vendor.%s.vrr.expected_present.timeout_ns",
216 displayTypeIdentifier.c_str());
217 mXrrSettings.notifyExpectedPresentConfig.TimeoutNs =
218 property_get_int32(pathBuffer, kDefaultNotifyExpectedPresentConfigTimeoutNs);
219 mXrrSettings.configChangeCallback =
220 std::bind(&ExynosPrimaryDisplay::onConfigChange, this, std::placeholders::_1);
221 } else {
222 setBit(refreshControlCommand, kPanelRefreshCtrlMrrV1OverV2Offset);
223 setBit(refreshControlCommand, kPanelRefreshCtrlFrameInsertionAutoModeOffset);
224 }
225
226 std::string displayFileNodePath = getPanelSysfsPath();
227 if (displayFileNodePath.empty()) {
228 ALOGE("%s(): cannot find file node %s of display %s", __func__,
229 displayFileNodePath.c_str(), mDisplayName.c_str());
230 } else {
231 auto& fileNodeManager =
232 android::hardware::graphics::composer::FileNodeManager::getInstance();
233 auto fileNode = fileNodeManager.getFileNode(displayFileNodePath);
234 auto content = fileNode->readString(kRefreshControlNodeName);
235 if (content.has_value() &&
236 !(content.value().compare(0, kRefreshControlNodeEnabled.length(),
237 kRefreshControlNodeEnabled))) {
238 bool ret = fileNode->writeValue(kRefreshControlNodeName, refreshControlCommand);
239 if (!ret) {
240 ALOGE("%s(): write command to file node %s%s failed.", __func__,
241 displayFileNodePath.c_str(), kRefreshControlNodeName.c_str());
242 }
243 } else {
244 ALOGI("%s(): refresh control is not supported", __func__);
245 }
246 }
247 mIsDisplayTempMonitorSupported = initDisplayTempMonitor(displayTypeIdentifier);
248 }
249
250 // Allow to enable dynamic recomposition after every power on
251 // since it will always be disabled for every power off
252 // TODO(b/268474771): to enable DR by default if video mode panel is detected
253 if (property_get_int32("vendor.display.dynamic_recomposition", 0) & (1 << index)) {
254 mDRDefault = true;
255 mDREnable = true;
256 }
257
258 // Prepare multi resolution
259 // Will be exynosHWCControl.multiResoultion
260 mResolutionInfo.nNum = 1;
261 mResolutionInfo.nResolution[0].w = 1440;
262 mResolutionInfo.nResolution[0].h = 2960;
263 mResolutionInfo.nDSCYSliceSize[0] = 40;
264 mResolutionInfo.nDSCXSliceSize[0] = 1440 / 2;
265 mResolutionInfo.nPanelType[0] = PANEL_DSC;
266 mResolutionInfo.nResolution[1].w = 1080;
267 mResolutionInfo.nResolution[1].h = 2220;
268 mResolutionInfo.nDSCYSliceSize[1] = 30;
269 mResolutionInfo.nDSCXSliceSize[1] = 1080 / 2;
270 mResolutionInfo.nPanelType[1] = PANEL_DSC;
271 mResolutionInfo.nResolution[2].w = 720;
272 mResolutionInfo.nResolution[2].h = 1480;
273 mResolutionInfo.nDSCYSliceSize[2] = 74;
274 mResolutionInfo.nDSCXSliceSize[2] = 720;
275 mResolutionInfo.nPanelType[2] = PANEL_LEGACY;
276
277 char value[PROPERTY_VALUE_MAX];
278 const char *earlyWakeupNodeBase = early_wakeup_node_0_base;
279 if (getDcDisplayType() == DisplayType::DISPLAY_SECONDARY &&
280 property_get("vendor.display.secondary_early_wakeup_node", value, "") > 0) {
281 earlyWakeupNodeBase = value;
282 }
283 mEarlyWakeupDispFd = fopen(earlyWakeupNodeBase, "w");
284 if (mEarlyWakeupDispFd == nullptr)
285 ALOGE("open %s failed! %s", earlyWakeupNodeBase, strerror(errno));
286 mBrightnessController = std::make_unique<BrightnessController>(
__anon1d2a27210202() 287 mIndex, [this]() { mDevice->onRefresh(mDisplayId); },
__anon1d2a27210302() 288 [this]() { updatePresentColorConversionInfo(); });
289 mHistogramController = std::make_unique<HistogramController>(this);
290
291 mDisplayControl.multiThreadedPresent = true;
292
293 int fixedTe2DefaultRateHz =
294 property_get_int32("vendor.primarydisplay.fixed_te2.default_rate_hz", 0);
295 if (fixedTe2DefaultRateHz) {
296 mDisplayTe2Manager =
297 std::make_unique<DisplayTe2Manager>(this, mIndex, fixedTe2DefaultRateHz);
298 }
299 }
300
~ExynosPrimaryDisplay()301 ExynosPrimaryDisplay::~ExynosPrimaryDisplay()
302 {
303 if (mEarlyWakeupDispFd) {
304 fclose(mEarlyWakeupDispFd);
305 mEarlyWakeupDispFd = nullptr;
306 }
307
308 if (mDisplayNeedHandleIdleExitOfs.is_open()) {
309 mDisplayNeedHandleIdleExitOfs.close();
310 }
311
312 if (mIsDisplayTempMonitorSupported) {
313 mTMLoopStatus.store(false, std::memory_order_relaxed);
314 mTMCondition.notify_one();
315 if (mTMThread.joinable()) {
316 mTMThread.join();
317 }
318 }
319 }
320
setDDIScalerEnable(int width,int height)321 void ExynosPrimaryDisplay::setDDIScalerEnable(int width, int height) {
322
323 if (exynosHWCControl.setDDIScaler == false) return;
324
325 ALOGI("DDISCALER Info : setDDIScalerEnable(w=%d,h=%d)", width, height);
326 mNewScaledWidth = width;
327 mNewScaledHeight = height;
328 mXres = width;
329 mYres = height;
330 }
331
getDDIScalerMode(int width,int height)332 int ExynosPrimaryDisplay::getDDIScalerMode(int width, int height) {
333
334 if (exynosHWCControl.setDDIScaler == false) return 1;
335
336 // Check if panel support support resolution or not.
337 for (uint32_t i=0; i < mResolutionInfo.nNum; i++) {
338 if (mResolutionInfo.nResolution[i].w * mResolutionInfo.nResolution[i].h ==
339 static_cast<uint32_t>(width * height))
340 return i + 1;
341 }
342
343 return 1; // WQHD
344 }
345
doDisplayConfigInternal(hwc2_config_t config)346 int32_t ExynosPrimaryDisplay::doDisplayConfigInternal(hwc2_config_t config) {
347 if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON) ||
348 !isConfigSettingEnabled()) {
349 mPendingConfig = config;
350 mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_DONE;
351 DISPLAY_LOGI("%s:: Pending desired Config: %d", __func__, config);
352 return NO_ERROR;
353 }
354 return ExynosDisplay::doDisplayConfigInternal(config);
355 }
356
getActiveConfigInternal(hwc2_config_t * outConfig)357 int32_t ExynosPrimaryDisplay::getActiveConfigInternal(hwc2_config_t *outConfig) {
358 if (outConfig && mPendingConfig != UINT_MAX) {
359 *outConfig = mPendingConfig;
360 return HWC2_ERROR_NONE;
361 }
362 return ExynosDisplay::getActiveConfigInternal(outConfig);
363 }
364
setActiveConfigInternal(hwc2_config_t config,bool force)365 int32_t ExynosPrimaryDisplay::setActiveConfigInternal(hwc2_config_t config, bool force) {
366 hwc2_config_t cur_config;
367
368 getActiveConfigInternal(&cur_config);
369 if (cur_config == config) {
370 ALOGI("%s:: Same display config is set", __func__);
371 return HWC2_ERROR_NONE;
372 }
373 if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON) ||
374 !isConfigSettingEnabled()) {
375 mPendingConfig = config;
376 return HWC2_ERROR_NONE;
377 }
378 return ExynosDisplay::setActiveConfigInternal(config, force);
379 }
380
381 // If a display is Off, applyPendingConfig() calls to setActiveConfig() that also
382 // power on the display by a blocking commit.
applyPendingConfig()383 int32_t ExynosPrimaryDisplay::applyPendingConfig() {
384 if (!isConfigSettingEnabled()) {
385 ALOGI("%s:: config setting is disabled", __func__);
386 if (mPowerModeState.has_value() && (*mPowerModeState == HWC2_POWER_MODE_ON)) {
387 ALOGI("%s:: skip apply pending config", __func__);
388 return HWC2_ERROR_NONE;
389 }
390 }
391
392 hwc2_config_t config;
393 if (mPendingConfig != UINT_MAX) {
394 ALOGI("%s:: mPendingConfig: %d", __func__, mPendingConfig);
395 config = mPendingConfig;
396 mPendingConfig = UINT_MAX;
397 } else {
398 getActiveConfigInternal(&config);
399 }
400
401 return ExynosDisplay::setActiveConfigInternal(config, true);
402 }
403
setBootDisplayConfig(int32_t config)404 int32_t ExynosPrimaryDisplay::setBootDisplayConfig(int32_t config) {
405 auto hwcConfig = static_cast<hwc2_config_t>(config);
406
407 const auto &it = mDisplayConfigs.find(hwcConfig);
408 if (it == mDisplayConfigs.end()) {
409 DISPLAY_LOGE("%s: invalid config %d", __func__, config);
410 return HWC2_ERROR_BAD_CONFIG;
411 }
412
413 const auto &mode = it->second;
414 if (mode.vsyncPeriod == 0)
415 return HWC2_ERROR_BAD_CONFIG;
416
417 char modeStr[PROPERTY_VALUE_MAX];
418 int ret = snprintf(modeStr, sizeof(modeStr), "%dx%d@%d:%d", mode.width, mode.height,
419 mode.refreshRate, nanoSec2Hz(mode.vsyncPeriod));
420 if (ret <= 0)
421 return HWC2_ERROR_BAD_CONFIG;
422
423 ALOGD("%s: mode=%s (%d)", __func__, modeStr, config);
424 ret = property_set(getPropertyBootModeStr(mDisplayId).c_str(), modeStr);
425
426 return !ret ? HWC2_ERROR_NONE : HWC2_ERROR_BAD_CONFIG;
427 }
428
clearBootDisplayConfig()429 int32_t ExynosPrimaryDisplay::clearBootDisplayConfig() {
430 auto ret = property_set(getPropertyBootModeStr(mDisplayId).c_str(), nullptr);
431
432 ALOGD("%s: clearing boot mode", __func__);
433 return !ret ? HWC2_ERROR_NONE : HWC2_ERROR_BAD_CONFIG;
434 }
435
getPreferredDisplayConfigInternal(int32_t * outConfig)436 int32_t ExynosPrimaryDisplay::getPreferredDisplayConfigInternal(int32_t *outConfig) {
437 char modeStr[PROPERTY_VALUE_MAX];
438 auto ret = property_get(getPropertyBootModeStr(mDisplayId).c_str(), modeStr, "");
439
440 if (ret <= 0) {
441 return mDisplayInterface->getDefaultModeId(outConfig);
442 }
443
444 int width, height;
445 int fps = 0, vsyncRate = 0;
446
447 ret = sscanf(modeStr, "%dx%d@%d:%d", &width, &height, &fps, &vsyncRate);
448 if (ret < 4) {
449 ret = sscanf(modeStr, "%dx%d@%d", &width, &height, &fps);
450 if ((ret < 3) || !fps) {
451 ALOGW("%s: unable to find boot config for mode: %s", __func__, modeStr);
452 return HWC2_ERROR_BAD_CONFIG;
453 }
454 if (lookupDisplayConfigs(width, height, fps, fps, outConfig) != HWC2_ERROR_NONE) {
455 ALOGE("%s: kernel doesn't support mode: %s", __func__, modeStr);
456 return HWC2_ERROR_BAD_CONFIG;
457 }
458 ret = setBootDisplayConfig(*outConfig);
459 if (ret == HWC2_ERROR_NONE)
460 ALOGI("%s: succeeded to replace %s with new format", __func__, modeStr);
461 else
462 ALOGE("%s: failed to replace %s with new format", __func__, modeStr);
463 return ret;
464 }
465 if (!fps || !vsyncRate || (fps > vsyncRate)) {
466 ALOGE("%s: bad boot config: %s", __func__, modeStr);
467 return HWC2_ERROR_BAD_CONFIG;
468 }
469 return lookupDisplayConfigs(width, height, fps, vsyncRate, outConfig);
470 }
471
setPowerOn()472 int32_t ExynosPrimaryDisplay::setPowerOn() {
473 ATRACE_CALL();
474 updateAppliedActiveConfig(0, 0);
475 int ret = NO_ERROR;
476 if (mDisplayId != 0 || !mFirstPowerOn) {
477 if (mDevice->hasOtherDisplayOn(this)) {
478 mResourceManager->prepareResources(mDisplayId);
479 // TODO: This is useful for cmd mode, and b/282094671 tries to handles video mode
480 mDisplayInterface->triggerClearDisplayPlanes();
481 }
482 ret = applyPendingConfig();
483 }
484
485 if (!mPowerModeState.has_value() || (*mPowerModeState == HWC2_POWER_MODE_OFF)) {
486 // check the dynamic recomposition thread by following display
487 mDevice->checkDynamicRecompositionThread();
488 if (ret) {
489 mDisplayInterface->setPowerMode(HWC2_POWER_MODE_ON);
490 }
491 setGeometryChanged(GEOMETRY_DISPLAY_POWER_ON);
492 }
493
494 {
495 std::lock_guard<std::mutex> lock(mPowerModeMutex);
496 mPowerModeState = HWC2_POWER_MODE_ON;
497 if (mNotifyPowerOn) {
498 mPowerOnCondition.notify_one();
499 mNotifyPowerOn = false;
500 }
501 }
502
503 if (mDisplayTe2Manager) mDisplayTe2Manager->restoreTe2FromDozeMode();
504
505 if (mFirstPowerOn) {
506 firstPowerOn();
507 }
508
509 return HWC2_ERROR_NONE;
510 }
511
setPowerOff()512 int32_t ExynosPrimaryDisplay::setPowerOff() {
513 ATRACE_CALL();
514
515 clearDisplay(true);
516
517 // check the dynamic recomposition thread by following display
518 mDevice->checkDynamicRecompositionThread();
519
520 mDisplayInterface->setPowerMode(HWC2_POWER_MODE_OFF);
521
522 {
523 std::lock_guard<std::mutex> lock(mPowerModeMutex);
524 mPowerModeState = HWC2_POWER_MODE_OFF;
525 }
526
527 /* It should be called from validate() when the screen is on */
528 mSkipFrame = true;
529 setGeometryChanged(GEOMETRY_DISPLAY_POWER_OFF);
530 if ((mRenderingState >= RENDERING_STATE_VALIDATED) &&
531 (mRenderingState < RENDERING_STATE_PRESENTED))
532 closeFencesForSkipFrame(RENDERING_STATE_VALIDATED);
533 mRenderingState = RENDERING_STATE_NONE;
534
535 // in the case user turns off screen when LHBM is on
536 // TODO: b/236433238 considering a lock for mLhbmOn state
537 mLhbmOn = false;
538 return HWC2_ERROR_NONE;
539 }
540
setPowerDoze(hwc2_power_mode_t mode)541 int32_t ExynosPrimaryDisplay::setPowerDoze(hwc2_power_mode_t mode) {
542 ATRACE_CALL();
543
544 if (!mDisplayInterface->isDozeModeAvailable()) {
545 return HWC2_ERROR_UNSUPPORTED;
546 }
547
548 if (mPowerModeState.has_value() &&
549 ((*mPowerModeState == HWC2_POWER_MODE_OFF) || (*mPowerModeState == HWC2_POWER_MODE_ON))) {
550 if (mDisplayInterface->setLowPowerMode()) {
551 ALOGI("Not support LP mode.");
552 return HWC2_ERROR_UNSUPPORTED;
553 }
554 }
555
556 {
557 std::lock_guard<std::mutex> lock(mPowerModeMutex);
558 mPowerModeState = mode;
559 }
560
561 // LHBM will be disabled in the kernel while entering AOD mode if it's
562 // already enabled. Reset the state to avoid the sync problem.
563 mBrightnessController->resetLhbmState();
564 mLhbmOn = false;
565
566 ExynosDisplay::updateRefreshRateHint();
567
568 if (mDisplayTe2Manager) mDisplayTe2Manager->updateTe2ForDozeMode();
569
570 return HWC2_ERROR_NONE;
571 }
572
setPowerMode(int32_t mode)573 int32_t ExynosPrimaryDisplay::setPowerMode(int32_t mode) {
574 Mutex::Autolock lock(mDisplayMutex);
575
576 if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::PAUSE)) {
577 mode = HWC2_POWER_MODE_OFF;
578 mPauseDisplay = true;
579 } else if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME)) {
580 mode = HWC2_POWER_MODE_ON;
581 mPauseDisplay = false;
582 } else if (mPauseDisplay) {
583 ALOGI("Skip power mode transition due to pause display.");
584 return HWC2_ERROR_NONE;
585 }
586
587 if (mPowerModeState.has_value() && (mode == static_cast<int32_t>(mPowerModeState.value()))) {
588 ALOGI("Skip power mode transition due to the same power state.");
589 return HWC2_ERROR_NONE;
590 }
591
592 if (mode == HWC2_POWER_MODE_ON && mDevice->mNumPrimaryDisplays >= 2) {
593 ExynosDisplay* external_display =
594 mDevice->getDisplay(getDisplayId(HWC_DISPLAY_EXTERNAL, 0));
595 ExynosDisplayDrmInterface* external_display_intf = external_display
596 ? static_cast<ExynosDisplayDrmInterface*>(external_display->mDisplayInterface.get())
597 : nullptr;
598 if (external_display_intf && external_display_intf->borrowedCrtcFrom() == this) {
599 ALOGI("Display %s is powering on, adjusting decon assignments",
600 mDisplayTraceName.c_str());
601 hwc2_config_t activeConfig = 0;
602 external_display->getActiveConfig(&activeConfig);
603 external_display->clearDisplay(true);
604 external_display->setPowerMode(HWC2_POWER_MODE_OFF);
605 // Restore the original decon assigned to external display, this will ensure
606 // primary displays remain on the same initially assigned decons.
607 external_display_intf->swapCrtcs(this);
608 // This display is about to be powered on, but its mPowerModeState is not updated yet,
609 // so we need to exclude it from consideration explicitly here.
610 ExynosDisplay* poweredOffPrimaryDisplay = mDevice->findPoweredOffPrimaryDisplay(this);
611 if (poweredOffPrimaryDisplay) {
612 ALOGI("Found powered off primary display %s, will use its decon for external "
613 "display",
614 poweredOffPrimaryDisplay->mDisplayTraceName.c_str());
615 external_display_intf->swapCrtcs(poweredOffPrimaryDisplay);
616 } else {
617 ALOGE("Could not find a powered off primary display!");
618 }
619 external_display->mActiveConfig = 0;
620 external_display->setActiveConfig(activeConfig);
621 external_display->setPowerMode(HWC2_POWER_MODE_ON);
622 }
623 }
624
625 int fb_blank = (mode != HWC2_POWER_MODE_OFF) ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
626 ALOGD("%s:: FBIOBLANK mode(%d), blank(%d)", __func__, mode, fb_blank);
627
628 if (fb_blank == FB_BLANK_POWERDOWN)
629 mDREnable = false;
630 else
631 mDREnable = mDRDefault;
632
633 if (mOperationRateManager) {
634 mOperationRateManager->onPowerMode(mode);
635 mBrightnessController->processOperationRate(
636 mOperationRateManager->getTargetOperationRate());
637 }
638
639 std::lock_guard<std::mutex> minIdleRefreshRateLock(mMinIdleRefreshRateMutex);
640 if (mVariableRefreshRateController) {
641 if ((mode == HWC2_POWER_MODE_DOZE) || (mode == HWC2_POWER_MODE_DOZE_SUSPEND)) {
642 mVariableRefreshRateController->setFixedRefreshRateRange(kMinIdleRefreshRateForDozeMode,
643 0);
644 }
645 mVariableRefreshRateController->preSetPowerMode(mode);
646 }
647
648 int32_t res = HWC2_ERROR_BAD_PARAMETER;
649 switch (mode) {
650 case HWC2_POWER_MODE_DOZE:
651 case HWC2_POWER_MODE_DOZE_SUSPEND: {
652 if (mode == HWC2_POWER_MODE_DOZE && mDisplayInterface->needRefreshOnLP()) {
653 ALOGI("Refresh before setting power doze.");
654 mDevice->onRefresh(mDisplayId);
655 }
656 res = setPowerDoze(static_cast<hwc2_power_mode_t>(mode));
657 break;
658 }
659 case HWC2_POWER_MODE_OFF:
660 res = setPowerOff();
661 break;
662 case HWC2_POWER_MODE_ON:
663 res = setPowerOn();
664 break;
665 default:
666 return res;
667 }
668 if (res != HWC2_ERROR_NONE) {
669 return res;
670 }
671
672 ExynosDisplay::updateRefreshRateHint();
673 if (mVariableRefreshRateController) {
674 mVariableRefreshRateController->postSetPowerMode(mode);
675 if (mode == HWC2_POWER_MODE_ON) {
676 mVariableRefreshRateController->setFixedRefreshRateRange(mMinIdleRefreshRate,
677 mRefreshRateDelayNanos);
678 }
679 }
680
681 checkTemperatureMonitorThread(mPowerModeState.has_value() && mode == HWC2_POWER_MODE_ON);
682
683 return res;
684 }
685
firstPowerOn()686 void ExynosPrimaryDisplay::firstPowerOn() {
687 SetCurrentPanelGammaSource(DisplayType::DISPLAY_PRIMARY, PanelGammaSource::GAMMA_CALIBRATION);
688 mFirstPowerOn = false;
689 getDisplayIdleTimerEnabled(mDisplayIdleTimerEnabled);
690 initDisplayHandleIdleExit();
691 }
692
getHDRException(ExynosLayer * __unused layer)693 bool ExynosPrimaryDisplay::getHDRException(ExynosLayer* __unused layer)
694 {
695 return false;
696 }
697
initDisplayInterface(uint32_t interfaceType)698 void ExynosPrimaryDisplay::initDisplayInterface(uint32_t interfaceType)
699 {
700 if (interfaceType == INTERFACE_TYPE_DRM)
701 mDisplayInterface = std::make_unique<ExynosPrimaryDisplayDrmInterfaceModule>((ExynosDisplay *)this);
702 else
703 LOG_ALWAYS_FATAL("%s::Unknown interface type(%d)",
704 __func__, interfaceType);
705 mDisplayInterface->init(this);
706
707 if (mXrrSettings.versionInfo.needVrrParameters()) {
708 mDisplayInterface->setXrrSettings(mXrrSettings);
709 }
710
711 mDpuData.init(mMaxWindowNum, mDevice->getSpecialPlaneNum(mDisplayId));
712 mLastDpuData.init(mMaxWindowNum, mDevice->getSpecialPlaneNum(mDisplayId));
713 ALOGI("window configs size(%zu) rcd configs zie(%zu)", mDpuData.configs.size(),
714 mDpuData.rcdConfigs.size());
715 }
716
getPanelSysfsPath(const DisplayType & type) const717 std::string ExynosPrimaryDisplay::getPanelSysfsPath(const DisplayType& type) const {
718 if ((type < DisplayType::DISPLAY_PRIMARY) || (type >= DisplayType::DISPLAY_MAX)) {
719 ALOGE("Invalid display panel type %d", type);
720 return {};
721 }
722
723 const auto& iter = panelSysfsPath.find(type);
724 if (iter == panelSysfsPath.end()) {
725 return {};
726 }
727
728 return iter->second;
729 }
730
SetCurrentPanelGammaSource(const DisplayType type,const PanelGammaSource & source)731 int32_t ExynosPrimaryDisplay::SetCurrentPanelGammaSource(const DisplayType type,
732 const PanelGammaSource &source) {
733 std::string &&panel_sysfs_path = getPanelSysfsPath(type);
734 if (panel_sysfs_path.empty()) {
735 return HWC2_ERROR_UNSUPPORTED;
736 }
737
738 std::ifstream ifs;
739 std::string &&path = panel_sysfs_path + "panel_name";
740 ifs.open(path, std::ifstream::in);
741 if (!ifs.is_open()) {
742 ALOGW("Unable to access panel name path '%s' (%s)", path.c_str(), strerror(errno));
743 return HWC2_ERROR_UNSUPPORTED;
744 }
745 std::string panel_name;
746 std::getline(ifs, panel_name);
747 ifs.close();
748
749 path = panel_sysfs_path + "serial_number";
750 ifs.open(path, std::ifstream::in);
751 if (!ifs.is_open()) {
752 ALOGW("Unable to access panel id path '%s' (%s)", path.c_str(), strerror(errno));
753 return HWC2_ERROR_UNSUPPORTED;
754 }
755 std::string panel_id;
756 std::getline(ifs, panel_id);
757 ifs.close();
758
759 std::string gamma_node = panel_sysfs_path + "gamma";
760 if (access(gamma_node.c_str(), W_OK)) {
761 ALOGW("Unable to access panel gamma calibration node '%s' (%s)", gamma_node.c_str(),
762 strerror(errno));
763 return HWC2_ERROR_UNSUPPORTED;
764 }
765
766 std::string &&gamma_data = "default";
767 if (source == PanelGammaSource::GAMMA_CALIBRATION) {
768 std::string gamma_cal_file(kDisplayCalFilePath);
769 gamma_cal_file.append(kPanelGammaCalFilePrefix)
770 .append(1, '_')
771 .append(panel_name)
772 .append(1, '_')
773 .append(panel_id)
774 .append(".cal");
775 if (access(gamma_cal_file.c_str(), R_OK)) {
776 ALOGI("Fail to access `%s` (%s), try golden gamma calibration", gamma_cal_file.c_str(),
777 strerror(errno));
778 gamma_cal_file = kDisplayCalFilePath;
779 gamma_cal_file.append(kPanelGammaCalFilePrefix)
780 .append(1, '_')
781 .append(panel_name)
782 .append(".cal");
783 }
784 gamma_data = loadPanelGammaCalibration(gamma_cal_file);
785 }
786
787 if (gamma_data.empty()) {
788 return HWC2_ERROR_UNSUPPORTED;
789 }
790
791 std::ofstream ofs(gamma_node);
792 if (!ofs.is_open()) {
793 ALOGW("Unable to open gamma node '%s', error = %s", gamma_node.c_str(), strerror(errno));
794 return HWC2_ERROR_UNSUPPORTED;
795 }
796 ofs.write(gamma_data.c_str(), gamma_data.size());
797 ofs.close();
798
799 currentPanelGammaSource = source;
800 return HWC2_ERROR_NONE;
801 }
802
isLhbmSupported()803 bool ExynosPrimaryDisplay::isLhbmSupported() {
804 return mBrightnessController->isLhbmSupported();
805 }
806
isConfigSettingEnabled()807 bool ExynosPrimaryDisplay::isConfigSettingEnabled() {
808 int64_t msSinceDisabled =
809 (systemTime(SYSTEM_TIME_MONOTONIC) - mConfigSettingDisabledTimestamp) / 1000000;
810 return !mConfigSettingDisabled || msSinceDisabled > kConfigDisablingMaxDurationMs;
811 }
812
enableConfigSetting(bool en)813 void ExynosPrimaryDisplay::enableConfigSetting(bool en) {
814 DISPLAY_ATRACE_INT("ConfigSettingDisabled", !en);
815 ALOGI("%s:: mConfigSettingDisabled: %d", __func__, !en);
816 if (!en) {
817 mConfigSettingDisabled = true;
818 mConfigSettingDisabledTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
819 return;
820 }
821
822 mConfigSettingDisabled = false;
823 }
824
getDisplayConfigs(uint32_t * outNumConfigs,hwc2_config_t * outConfigs)825 int32_t ExynosPrimaryDisplay::getDisplayConfigs(uint32_t* outNumConfigs,
826 hwc2_config_t* outConfigs) {
827 int32_t ret = ExynosDisplay::getDisplayConfigs(outNumConfigs, outConfigs);
828 if (ret == HWC2_ERROR_NONE) {
829 if (mXrrSettings.versionInfo.hasVrrController() && mDisplayConfigs.size()) {
830 if (!mVariableRefreshRateController) {
831 mVariableRefreshRateController =
832 VariableRefreshRateController::CreateInstance(this, getPanelName());
833 std::unordered_map<hwc2_config_t, VrrConfig_t> vrrConfigs;
834 for (const auto& it : mDisplayConfigs) {
835 if (!it.second.vrrConfig.has_value()) {
836 ALOGE("Both pseudo and full VRR modes should include VRR configurations.");
837 return HWC2_ERROR_BAD_CONFIG;
838 }
839 vrrConfigs[it.first] = it.second.vrrConfig.value();
840 }
841 mVariableRefreshRateController->setVrrConfigurations(std::move(vrrConfigs));
842 hwc2_config_t activeConfig;
843 if (ExynosDisplay::getActiveConfig(&activeConfig) == HWC2_ERROR_NONE) {
844 mVariableRefreshRateController->setActiveVrrConfiguration(activeConfig);
845 mVariableRefreshRateController->setEnable(true);
846 }
847 }
848 }
849 }
850 return ret;
851 }
852
presentDisplay(int32_t * outRetireFence)853 int32_t ExynosPrimaryDisplay::presentDisplay(int32_t* outRetireFence) {
854 auto res = ExynosDisplay::presentDisplay(outRetireFence);
855 // Forward presentDisplay if there is a listener.
856 const auto refreshListener = getRefreshListener();
857 if (res == HWC2_ERROR_NONE && refreshListener) {
858 refreshListener->onPresent(*outRetireFence);
859 }
860 return res;
861 }
862
onVsync(int64_t timestamp)863 void ExynosPrimaryDisplay::onVsync(int64_t timestamp) {
864 const auto vsyncListener = getVsyncListener();
865 if (vsyncListener) {
866 vsyncListener->onVsync(timestamp, 0);
867 }
868 }
869
notifyExpectedPresent(int64_t timestamp,int32_t frameIntervalNs)870 int32_t ExynosPrimaryDisplay::notifyExpectedPresent(int64_t timestamp, int32_t frameIntervalNs) {
871 DISPLAY_ATRACE_INT64("expectedPresentTimeDelta", timestamp - systemTime());
872 DISPLAY_ATRACE_INT("frameInterval", frameIntervalNs);
873 if (mVariableRefreshRateController) {
874 mVariableRefreshRateController->notifyExpectedPresent(timestamp, frameIntervalNs);
875 }
876 return NO_ERROR;
877 }
878
setPresentTimeoutParameters(int timeoutNs,const std::vector<std::pair<uint32_t,uint32_t>> & settings)879 int32_t ExynosPrimaryDisplay::setPresentTimeoutParameters(
880 int timeoutNs, const std::vector<std::pair<uint32_t, uint32_t>>& settings) {
881 if (mVariableRefreshRateController) {
882 mVariableRefreshRateController->setPresentTimeoutParameters(timeoutNs, settings);
883 return NO_ERROR;
884 }
885 return HWC2_ERROR_UNSUPPORTED;
886 }
887
setPresentTimeoutController(uint32_t controllerType)888 int32_t ExynosPrimaryDisplay::setPresentTimeoutController(uint32_t controllerType) {
889 if (mVariableRefreshRateController) {
890 mVariableRefreshRateController->setPresentTimeoutController(controllerType);
891 return NO_ERROR;
892 }
893 return HWC2_ERROR_UNSUPPORTED;
894 }
895
setRefreshRateChangedCallbackDebugEnabled(bool enabled)896 int32_t ExynosPrimaryDisplay::setRefreshRateChangedCallbackDebugEnabled(bool enabled) {
897 if (mVariableRefreshRateController) {
898 mVariableRefreshRateController->enableRefreshRateCalculator(enabled);
899 } else {
900 ExynosDisplay::setRefreshRateChangedCallbackDebugEnabled(enabled);
901 }
902 return NO_ERROR;
903 }
904
setLhbmDisplayConfigLocked(uint32_t peakRate)905 int32_t ExynosPrimaryDisplay::setLhbmDisplayConfigLocked(uint32_t peakRate) {
906 auto hwConfig = mDisplayInterface->getActiveModeId();
907 auto config = getConfigId(peakRate, mDisplayConfigs[hwConfig].width,
908 mDisplayConfigs[hwConfig].height);
909 if (config == UINT_MAX) {
910 DISPLAY_LOGE("%s: failed to get config for rate=%d", __func__, peakRate);
911 return -EINVAL;
912 }
913
914 if (mPendingConfig == UINT_MAX && mActiveConfig != config) mPendingConfig = mActiveConfig;
915 if (config != hwConfig) {
916 if (ExynosDisplay::setActiveConfigInternal(config, true) == HWC2_ERROR_NONE) {
917 DISPLAY_LOGI("%s: succeeded to set config=%d rate=%d", __func__, config, peakRate);
918 } else {
919 DISPLAY_LOGW("%s: failed to set config=%d rate=%d", __func__, config, peakRate);
920 }
921 } else {
922 DISPLAY_LOGI("%s: keep config=%d rate=%d", __func__, config, peakRate);
923 }
924 enableConfigSetting(false);
925 return OK;
926 }
927
restoreLhbmDisplayConfigLocked()928 void ExynosPrimaryDisplay::restoreLhbmDisplayConfigLocked() {
929 enableConfigSetting(true);
930
931 if (*mPowerModeState == HWC2_POWER_MODE_DOZE ||
932 *mPowerModeState == HWC2_POWER_MODE_DOZE_SUSPEND) {
933 DISPLAY_LOGI("%s: in aod mode(%d), skip restore", __func__, *mPowerModeState);
934 return;
935 }
936
937 hwc2_config_t pendingConfig = mPendingConfig;
938 auto hwConfig = mDisplayInterface->getActiveModeId();
939 if (pendingConfig != UINT_MAX && pendingConfig != hwConfig) {
940 if (applyPendingConfig() == HWC2_ERROR_NONE) {
941 DISPLAY_LOGI("%s: succeeded to set config=%d rate=%d", __func__, pendingConfig,
942 getRefreshRate(pendingConfig));
943 } else {
944 DISPLAY_LOGE("%s: failed to set config=%d rate=%d", __func__, pendingConfig,
945 getRefreshRate(pendingConfig));
946 }
947 } else {
948 mPendingConfig = UINT_MAX;
949 DISPLAY_LOGI("%s: keep config=%d rate=%d", __func__, hwConfig, getRefreshRate(hwConfig));
950 }
951 }
952
953 // This function should be called by other threads (e.g. sensor HAL).
954 // HWCService can call this function but it should be for test purpose only.
setLhbmState(bool enabled)955 int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) {
956 int ret = OK;
957 // NOTE: mLhbmOn could be set to false at any time by setPowerOff in another
958 // thread. Make sure no side effect if that happens. Or add lock if we have
959 // to when new code is added.
960 DISPLAY_ATRACE_CALL();
961 DISPLAY_LOGI("%s: enabled=%d", __func__, enabled);
962 {
963 ATRACE_NAME("wait_for_power_on");
964 std::unique_lock<std::mutex> lock(mPowerModeMutex);
965 if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON)) {
966 mNotifyPowerOn = true;
967 if (!mPowerOnCondition.wait_for(lock, std::chrono::milliseconds(2000), [this]() {
968 return (mPowerModeState.has_value() &&
969 (*mPowerModeState == HWC2_POWER_MODE_ON));
970 })) {
971 DISPLAY_LOGW("%s: wait for power mode on timeout !", __func__);
972 return TIMED_OUT;
973 }
974 }
975 }
976
977 auto lhbmSysfs = mBrightnessController->GetPanelSysfileByIndex(
978 BrightnessController::kLocalHbmModeFileNode);
979 ret = mBrightnessController->checkSysfsStatus(lhbmSysfs,
980 {std::to_string(static_cast<int>(
981 BrightnessController::LhbmMode::DISABLED))},
982 0);
983 bool wasDisabled = ret == OK;
984 if (!enabled && wasDisabled) {
985 DISPLAY_LOGW("%s: lhbm is at DISABLED state, skip disabling", __func__);
986 return NO_ERROR;
987 } else if (enabled && !wasDisabled) {
988 requestLhbm(true);
989 DISPLAY_LOGI("%s: lhbm is at ENABLING or ENABLED state, re-enable to reset timeout timer",
990 __func__);
991 return NO_ERROR;
992 }
993
994 std::vector<std::string> checkingValue;
995 if (!enabled) {
996 ATRACE_NAME("disable_lhbm");
997 requestLhbm(false);
998 {
999 ATRACE_NAME("wait_for_lhbm_off_cmd");
1000 checkingValue = {
1001 std::to_string(static_cast<int>(BrightnessController::LhbmMode::DISABLED))};
1002 ret = mBrightnessController->checkSysfsStatus(lhbmSysfs, checkingValue,
1003 ms2ns(kSysfsCheckTimeoutMs));
1004 if (ret != OK) {
1005 DISPLAY_LOGW("%s: failed to send lhbm-off cmd", __func__);
1006 }
1007 }
1008 {
1009 Mutex::Autolock lock(mDisplayMutex);
1010 restoreLhbmDisplayConfigLocked();
1011 }
1012 setLHBMRefreshRateThrottle(0);
1013 mLhbmOn = false;
1014 return NO_ERROR;
1015 }
1016
1017 ATRACE_NAME("enable_lhbm");
1018 int64_t lhbmWaitForRrNanos, lhbmEnablingNanos, lhbmEnablingDoneNanos;
1019 bool enablingStateSupported = !mFramesToReachLhbmPeakBrightness;
1020 uint32_t peakRate = 0;
1021 auto rrSysfs = mBrightnessController->GetPanelRefreshRateSysfile();
1022 lhbmWaitForRrNanos = systemTime(SYSTEM_TIME_MONOTONIC);
1023 {
1024 Mutex::Autolock lock(mDisplayMutex);
1025 peakRate = getPeakRefreshRate();
1026 if (peakRate < 60) {
1027 DISPLAY_LOGE("%s: invalid peak rate=%d", __func__, peakRate);
1028 return -EINVAL;
1029 }
1030 ret = setLhbmDisplayConfigLocked(peakRate);
1031 if (ret != OK) return ret;
1032 }
1033
1034 if (mBrightnessController->fileExists(rrSysfs)) {
1035 ATRACE_NAME("wait_for_peak_rate_cmd");
1036 ret = mBrightnessController->checkSysfsStatus(rrSysfs, {std::to_string(peakRate)},
1037 ms2ns(kLhbmWaitForPeakRefreshRateMs));
1038 if (ret != OK) {
1039 DISPLAY_LOGW("%s: failed to poll peak refresh rate=%d, ret=%d", __func__, peakRate,
1040 ret);
1041 }
1042 } else {
1043 ATRACE_NAME("wait_for_peak_rate_blindly");
1044 DISPLAY_LOGW("%s: missing refresh rate path: %s", __func__, rrSysfs.c_str());
1045 // blindly wait for (3 full frames + 1 frame uncertainty) to ensure DM finishes
1046 // switching refresh rate
1047 for (int32_t i = 0; i < 4; i++) {
1048 if (mDisplayInterface->waitVBlank()) {
1049 DISPLAY_LOGE("%s: failed to blindly wait for peak refresh rate=%d, i=%d", __func__,
1050 peakRate, i);
1051 ret = -ENODEV;
1052 goto enable_err;
1053 }
1054 }
1055 }
1056
1057 setLHBMRefreshRateThrottle(kLhbmRefreshRateThrottleMs);
1058 checkingValue = {std::to_string(static_cast<int>(BrightnessController::LhbmMode::ENABLING)),
1059 std::to_string(static_cast<int>(BrightnessController::LhbmMode::ENABLED))};
1060 lhbmEnablingNanos = systemTime(SYSTEM_TIME_MONOTONIC);
1061 requestLhbm(true);
1062 {
1063 ATRACE_NAME("wait_for_lhbm_on_cmd");
1064 ret = mBrightnessController->checkSysfsStatus(lhbmSysfs, checkingValue,
1065 ms2ns(kSysfsCheckTimeoutMs));
1066 if (ret != OK) {
1067 DISPLAY_LOGE("%s: failed to enable lhbm", __func__);
1068 setLHBMRefreshRateThrottle(0);
1069 goto enable_err;
1070 }
1071 }
1072
1073 lhbmEnablingDoneNanos = systemTime(SYSTEM_TIME_MONOTONIC);
1074 {
1075 ATRACE_NAME("wait_for_peak_brightness");
1076 if (enablingStateSupported) {
1077 ret = mBrightnessController->checkSysfsStatus(lhbmSysfs,
1078 {std::to_string(static_cast<int>(
1079 BrightnessController::LhbmMode::ENABLED))},
1080 ms2ns(kSysfsCheckTimeoutMs));
1081 if (ret != OK) {
1082 DISPLAY_LOGE("%s: failed to wait for lhbm becoming effective", __func__);
1083 goto enable_err;
1084 }
1085 } else {
1086 // lhbm takes effect at next vblank
1087 for (int32_t i = mFramesToReachLhbmPeakBrightness + 1; i > 0; i--) {
1088 ret = mDisplayInterface->waitVBlank();
1089 if (ret) {
1090 DISPLAY_LOGE("%s: failed to wait vblank for peak brightness, %d", __func__, i);
1091 goto enable_err;
1092 }
1093 }
1094 }
1095 }
1096 DISPLAY_LOGI("%s: latency: %04d = %03d|rr@%03d + %03d|en + %03d|boost@%s", __func__,
1097 getTimestampDeltaMs(0, lhbmWaitForRrNanos),
1098 getTimestampDeltaMs(lhbmEnablingNanos, lhbmWaitForRrNanos), peakRate,
1099 getTimestampDeltaMs(lhbmEnablingDoneNanos, lhbmEnablingNanos),
1100 getTimestampDeltaMs(0, lhbmEnablingDoneNanos),
1101 enablingStateSupported ? "polling" : "fixed");
1102
1103 mLhbmOn = true;
1104 if (!mPowerModeState.has_value() || (*mPowerModeState == HWC2_POWER_MODE_OFF && mLhbmOn)) {
1105 mLhbmOn = false;
1106 DISPLAY_LOGE("%s: power off during request lhbm on", __func__);
1107 return -EINVAL;
1108 }
1109 return NO_ERROR;
1110 enable_err:
1111 {
1112 // We may receive LHBM request during the power off sequence due to the
1113 // race condition between display and sensor. If the failure happens
1114 // after requestLhbm(), we will get a wrong LHBM state in the 1st commit
1115 // after power on. We should reset the state in this case.
1116 std::unique_lock<std::mutex> lock(mPowerModeMutex);
1117 if (!mPowerModeState.has_value() || (*mPowerModeState == HWC2_POWER_MODE_OFF)) {
1118 DISPLAY_LOGW("%s: request lhbm during power off sequence, reset the state", __func__);
1119 mBrightnessController->resetLhbmState();
1120 }
1121 }
1122
1123 Mutex::Autolock lock(mDisplayMutex);
1124 restoreLhbmDisplayConfigLocked();
1125 return ret;
1126 }
1127
getLhbmState()1128 bool ExynosPrimaryDisplay::getLhbmState() {
1129 return mLhbmOn;
1130 }
1131
setLHBMRefreshRateThrottle(const uint32_t delayMs)1132 void ExynosPrimaryDisplay::setLHBMRefreshRateThrottle(const uint32_t delayMs) {
1133 ATRACE_CALL();
1134
1135 if (delayMs) {
1136 // make new throttle take effect
1137 mLastRefreshRateAppliedNanos = systemTime(SYSTEM_TIME_MONOTONIC);
1138 DISPLAY_ATRACE_INT64("LastRefreshRateAppliedMs", ns2ms(mLastRefreshRateAppliedNanos));
1139 }
1140
1141 setRefreshRateThrottleNanos(std::chrono::duration_cast<std::chrono::nanoseconds>(
1142 std::chrono::milliseconds(delayMs))
1143 .count(),
1144 RrThrottleRequester::LHBM);
1145 }
1146
setEarlyWakeupDisplay()1147 void ExynosPrimaryDisplay::setEarlyWakeupDisplay() {
1148 if (mEarlyWakeupDispFd) {
1149 writeFileNode(mEarlyWakeupDispFd, 1);
1150 }
1151 }
1152
setExpectedPresentTime(uint64_t timestamp,int frameIntervalNs)1153 void ExynosPrimaryDisplay::setExpectedPresentTime(uint64_t timestamp, int frameIntervalNs) {
1154 DISPLAY_ATRACE_INT64("expectedPresentTimeDelta", timestamp - systemTime());
1155 DISPLAY_ATRACE_INT("frameInterval", frameIntervalNs);
1156
1157 mExpectedPresentTimeAndInterval.store(std::make_tuple(timestamp, frameIntervalNs));
1158 // Forward presentDisplay if there is a listener.
1159 const auto refreshListener = getRefreshListener();
1160 if (refreshListener) {
1161 refreshListener->setExpectedPresentTime(timestamp, frameIntervalNs);
1162 }
1163 }
1164
getPendingExpectedPresentTime()1165 uint64_t ExynosPrimaryDisplay::getPendingExpectedPresentTime() {
1166 if (mExpectedPresentTimeAndInterval.is_dirty()) {
1167 return std::get<0>(mExpectedPresentTimeAndInterval.get());
1168 }
1169
1170 return 0;
1171 }
1172
getPendingFrameInterval()1173 int ExynosPrimaryDisplay::getPendingFrameInterval() {
1174 if (mExpectedPresentTimeAndInterval.is_dirty()) {
1175 return std::get<1>(mExpectedPresentTimeAndInterval.get());
1176 }
1177
1178 return 0;
1179 }
1180
applyExpectedPresentTime()1181 void ExynosPrimaryDisplay::applyExpectedPresentTime() {
1182 mExpectedPresentTimeAndInterval.clear_dirty();
1183 }
1184
setDisplayIdleTimer(const int32_t timeoutMs)1185 int32_t ExynosPrimaryDisplay::setDisplayIdleTimer(const int32_t timeoutMs) {
1186 bool support = false;
1187 if (getDisplayIdleTimerSupport(support) || support == false) {
1188 return HWC2_ERROR_UNSUPPORTED;
1189 }
1190
1191 if (timeoutMs < 0) {
1192 return HWC2_ERROR_BAD_PARAMETER;
1193 }
1194
1195 if (timeoutMs > 0) {
1196 setDisplayIdleDelayNanos(std::chrono::duration_cast<std::chrono::nanoseconds>(
1197 std::chrono::milliseconds(timeoutMs))
1198 .count(),
1199 DispIdleTimerRequester::SF);
1200 }
1201
1202 bool enabled = (timeoutMs > 0);
1203 if (enabled != mDisplayIdleTimerEnabled) {
1204 if (setDisplayIdleTimerEnabled(enabled) == NO_ERROR) {
1205 mDisplayIdleTimerEnabled = enabled;
1206 }
1207 }
1208
1209 return HWC2_ERROR_NONE;
1210 }
1211
getDisplayIdleTimerEnabled(bool & enabled)1212 int32_t ExynosPrimaryDisplay::getDisplayIdleTimerEnabled(bool &enabled) {
1213 bool support = false;
1214 if (getDisplayIdleTimerSupport(support) || support == false) {
1215 return HWC2_ERROR_UNSUPPORTED;
1216 }
1217
1218 const std::string path = getPanelSysfsPath() + "panel_idle";
1219 std::ifstream ifs(path);
1220 if (!ifs.is_open()) {
1221 ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
1222 return errno;
1223 } else {
1224 std::string panel_idle;
1225 std::getline(ifs, panel_idle);
1226 ifs.close();
1227 enabled = (panel_idle == "1");
1228 ALOGI("%s() get panel_idle(%d) from the sysfs node", __func__, enabled);
1229 }
1230 return NO_ERROR;
1231 }
1232
setDisplayIdleTimerEnabled(const bool enabled)1233 int32_t ExynosPrimaryDisplay::setDisplayIdleTimerEnabled(const bool enabled) {
1234 const std::string path = getPanelSysfsPath() + "panel_idle";
1235 std::ofstream ofs(path);
1236 if (!ofs.is_open()) {
1237 ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
1238 return errno;
1239 } else {
1240 ofs << enabled;
1241 ofs.close();
1242 ALOGI("%s() writes panel_idle(%d) to the sysfs node", __func__, enabled);
1243 }
1244 return NO_ERROR;
1245 }
1246
setDisplayIdleDelayNanos(const int32_t delayNanos,const DispIdleTimerRequester requester)1247 int32_t ExynosPrimaryDisplay::setDisplayIdleDelayNanos(const int32_t delayNanos,
1248 const DispIdleTimerRequester requester) {
1249 std::lock_guard<std::mutex> lock(mDisplayIdleDelayMutex);
1250
1251 int64_t maxDelayNanos = 0;
1252 mDisplayIdleTimerNanos[toUnderlying(requester)] = delayNanos;
1253 for (uint32_t i = 0; i < toUnderlying(DispIdleTimerRequester::MAX); i++) {
1254 if (mDisplayIdleTimerNanos[i] > maxDelayNanos) {
1255 maxDelayNanos = mDisplayIdleTimerNanos[i];
1256 }
1257 }
1258
1259 if (mDisplayIdleDelayNanos == maxDelayNanos) {
1260 return NO_ERROR;
1261 }
1262
1263 mDisplayIdleDelayNanos = maxDelayNanos;
1264
1265 const int32_t displayIdleDelayMs = std::chrono::duration_cast<std::chrono::milliseconds>(
1266 std::chrono::nanoseconds(mDisplayIdleDelayNanos))
1267 .count();
1268 const std::string path = getPanelSysfsPath() + "idle_delay_ms";
1269 std::ofstream ofs(path);
1270 if (!ofs.is_open()) {
1271 ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
1272 return errno;
1273 } else {
1274 ofs << displayIdleDelayMs;
1275 ALOGI("%s() writes idle_delay_ms(%d) to the sysfs node (0x%x)", __func__,
1276 displayIdleDelayMs, ofs.rdstate());
1277 ofs.close();
1278 }
1279 return NO_ERROR;
1280 }
1281
initDisplayHandleIdleExit()1282 void ExynosPrimaryDisplay::initDisplayHandleIdleExit() {
1283 if (bool support; getDisplayIdleTimerSupport(support) || support == false) {
1284 return;
1285 }
1286
1287 const std::string path = getPanelSysfsPath() + "panel_need_handle_idle_exit";
1288 mDisplayNeedHandleIdleExitOfs.open(path, std::ofstream::out);
1289 if (!mDisplayNeedHandleIdleExitOfs.is_open()) {
1290 ALOGI("%s() '%s' doesn't exist(%s)", __func__, path.c_str(), strerror(errno));
1291 }
1292
1293 setDisplayNeedHandleIdleExit(false, true);
1294 }
1295
setDisplayNeedHandleIdleExit(const bool needed,const bool force)1296 void ExynosPrimaryDisplay::setDisplayNeedHandleIdleExit(const bool needed, const bool force) {
1297 if (!mDisplayNeedHandleIdleExitOfs.is_open()) {
1298 return;
1299 }
1300
1301 if (needed == mDisplayNeedHandleIdleExit && !force) {
1302 return;
1303 }
1304
1305 mDisplayNeedHandleIdleExitOfs << needed;
1306 if (mDisplayNeedHandleIdleExitOfs.fail()) {
1307 ALOGW("%s() failed to write panel_need_handle_idle_exit(%d) to sysfs node %s", __func__,
1308 needed, strerror(errno));
1309 return;
1310 }
1311
1312 mDisplayNeedHandleIdleExitOfs.flush();
1313 if (mDisplayNeedHandleIdleExitOfs.fail()) {
1314 ALOGW("%s() failed to flush panel_need_handle_idle_exit(%d) to sysfs node %s", __func__,
1315 needed, strerror(errno));
1316 return;
1317 }
1318
1319 ALOGI("%s() writes panel_need_handle_idle_exit(%d) to sysfs node", __func__, needed);
1320 mDisplayNeedHandleIdleExit = needed;
1321 }
1322
handleDisplayIdleEnter(const uint32_t idleTeRefreshRate)1323 void ExynosPrimaryDisplay::handleDisplayIdleEnter(const uint32_t idleTeRefreshRate) {
1324 bool needed = false;
1325 {
1326 Mutex::Autolock lock1(mDisplayMutex);
1327 uint32_t btsRefreshRate = getBtsRefreshRate();
1328 if (idleTeRefreshRate <= btsRefreshRate) {
1329 return;
1330 }
1331 Mutex::Autolock lock2(mDRMutex);
1332 for (size_t i = 0; i < mLayers.size(); i++) {
1333 if (mLayers[i]->mOtfMPP && mLayers[i]->mM2mMPP == nullptr &&
1334 !mLayers[i]->checkBtsCap(idleTeRefreshRate)) {
1335 needed = true;
1336 break;
1337 }
1338 }
1339 }
1340
1341 setDisplayNeedHandleIdleExit(needed, false);
1342 }
1343
setFixedTe2Rate(const int targetTe2RateHz)1344 int32_t ExynosPrimaryDisplay::setFixedTe2Rate(const int targetTe2RateHz) {
1345 if (mDisplayTe2Manager) {
1346 return mDisplayTe2Manager->setFixedTe2Rate(targetTe2RateHz);
1347 } else {
1348 return HWC2_ERROR_UNSUPPORTED;
1349 }
1350 }
1351
setDisplayTemperature(const int temperature)1352 int32_t ExynosPrimaryDisplay::setDisplayTemperature(const int temperature) {
1353 mDisplayTemperature = temperature;
1354 return HWC2_ERROR_UNSUPPORTED;
1355 }
1356
onProximitySensorStateChanged(bool active)1357 void ExynosPrimaryDisplay::onProximitySensorStateChanged(bool active) {
1358 if (mProximitySensorStateChangeCallback) {
1359 ALOGI("ExynosPrimaryDisplay: %s: %d", __func__, active);
1360 ATRACE_NAME("onProximitySensorStateChanged(HAL)");
1361 mProximitySensorStateChangeCallback->onProximitySensorStateChanged(active);
1362 }
1363 }
1364
setMinIdleRefreshRate(const int targetFps,const RrThrottleRequester requester)1365 int32_t ExynosPrimaryDisplay::setMinIdleRefreshRate(const int targetFps,
1366 const RrThrottleRequester requester) {
1367 if (targetFps < 0) {
1368 return HWC2_ERROR_BAD_PARAMETER;
1369 }
1370 int fps = targetFps;
1371 if ((requester == RrThrottleRequester::BRIGHTNESS) &&
1372 (!mBrightnessBlockingZonesLookupTable.empty())) {
1373 std::unique_lock<std::mutex> lock(mPowerModeMutex);
1374 // Only check the BRIGHTNESS vote when the power is on.
1375 if (mPowerModeState.has_value() && (*mPowerModeState == HWC2_POWER_MODE_ON)) {
1376 auto res = mBrightnessController->getBrightnessNitsAndMode();
1377 if (res != std::nullopt) {
1378 const auto it =
1379 mBrightnessBlockingZonesLookupTable.upper_bound(std::get<0>(res.value()));
1380 ALOGD("%s requester = BRIGHTNESS, brightness = %f nits, vote minimum refresh rate "
1381 "to %d",
1382 __func__, std::get<0>(res.value()), it->second);
1383 fps = std::max(fps, it->second);
1384 if (mDisplayConfigs.count(mActiveConfig)) {
1385 if (fps > mDisplayConfigs[mActiveConfig].refreshRate) {
1386 ALOGI("%s() The brightness blocking zone votes for the FPS = %d, which is "
1387 "higher than the maximum refresh rate of the current configuration = "
1388 "%d",
1389 __func__, fps, mDisplayConfigs[mActiveConfig].refreshRate);
1390 fps = mDisplayConfigs[mActiveConfig].refreshRate;
1391 }
1392 }
1393 }
1394 }
1395 }
1396
1397 std::lock_guard<std::mutex> lock(mMinIdleRefreshRateMutex);
1398 if (fps == mRrThrottleFps[toUnderlying(requester)]) return NO_ERROR;
1399
1400 ALOGD("%s requester %u, fps %d", __func__, toUnderlying(requester), fps);
1401 mRrThrottleFps[toUnderlying(requester)] = fps;
1402 int maxMinIdleFps = 0;
1403 for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
1404 if (mRrThrottleFps[i] > maxMinIdleFps) {
1405 maxMinIdleFps = mRrThrottleFps[i];
1406 }
1407 }
1408
1409 {
1410 std::lock_guard<std::mutex> lock(mPowerModeMutex);
1411 bool dozeMode = (mPowerModeState.has_value() &&
1412 (*mPowerModeState == HWC2_POWER_MODE_DOZE ||
1413 *mPowerModeState == HWC2_POWER_MODE_DOZE_SUSPEND));
1414 // Currently only proximity sensor will request the min refresh rate via this API with
1415 // PIXEL_DISP (or TEST for the debugging command). It will request a non-zero value,
1416 // e.g. 30Hz, if it's active, and request zero if it's inactive. So we can know its state
1417 // and update the TE2 option accordingly.
1418 if (mDisplayTe2Manager &&
1419 (requester == RrThrottleRequester::PIXEL_DISP ||
1420 requester == RrThrottleRequester::TEST)) {
1421 bool proximityActive = !!targetFps;
1422 ALOGD("%s: proximity state %s, min %dhz, doze mode %d", __func__,
1423 proximityActive ? "active" : "inactive", targetFps, dozeMode);
1424 mDisplayTe2Manager->updateTe2OptionForProximity(proximityActive, targetFps, dozeMode);
1425 if (!dozeMode) {
1426 mDisplayTe2Manager->handleProximitySensorStateChange(proximityActive);
1427 }
1428 }
1429
1430 if (maxMinIdleFps == mMinIdleRefreshRate) return NO_ERROR;
1431
1432 if (mVariableRefreshRateController) {
1433 if (dozeMode && maxMinIdleFps != kMinIdleRefreshRateForDozeMode) {
1434 ALOGW("%s: setting %dhz in doze mode (expect %dhz)", __func__, maxMinIdleFps,
1435 kMinIdleRefreshRateForDozeMode);
1436 mMinIdleRefreshRate = maxMinIdleFps;
1437 return NO_ERROR;
1438 }
1439
1440 int ret = mVariableRefreshRateController
1441 ->setFixedRefreshRateRange(maxMinIdleFps, mRefreshRateDelayNanos);
1442 if (ret >= 0) {
1443 mMinIdleRefreshRate = maxMinIdleFps;
1444 return NO_ERROR;
1445 }
1446 return ret;
1447 }
1448 }
1449
1450 const std::string path = getPanelSysfsPath() + "min_vrefresh";
1451 std::ofstream ofs(path);
1452 if (!ofs.is_open()) {
1453 ALOGW("%s Unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
1454 return errno;
1455 } else {
1456 ofs << maxMinIdleFps;
1457 ofs.close();
1458 ALOGI("ExynosPrimaryDisplay::%s() writes min_vrefresh(%d) to the sysfs node", __func__,
1459 maxMinIdleFps);
1460 }
1461 mMinIdleRefreshRate = maxMinIdleFps;
1462 return NO_ERROR;
1463 }
1464
setRefreshRateThrottleNanos(const int64_t delayNanos,const RrThrottleRequester requester)1465 int32_t ExynosPrimaryDisplay::setRefreshRateThrottleNanos(const int64_t delayNanos,
1466 const RrThrottleRequester requester) {
1467 ATRACE_CALL();
1468 if (delayNanos < 0) {
1469 ALOGW("%s() set invalid delay(%" PRId64 ")", __func__, delayNanos);
1470 return BAD_VALUE;
1471 }
1472
1473 int32_t ret = NO_ERROR;
1474 int64_t maxDelayNanos = 0;
1475 {
1476 std::lock_guard<std::mutex> lock(mIdleRefreshRateThrottleMutex);
1477 if (delayNanos == mRrThrottleNanos[toUnderlying(requester)]) return NO_ERROR;
1478
1479 ALOGI("%s() requester(%u) set delay to %" PRId64 "ns", __func__, toUnderlying(requester),
1480 delayNanos);
1481 mRrThrottleNanos[toUnderlying(requester)] = delayNanos;
1482 uint32_t maxDelayRequester = toUnderlying(RrThrottleRequester::MAX);
1483 for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
1484 if (mRrThrottleNanos[i] > maxDelayNanos) {
1485 maxDelayRequester = i;
1486 maxDelayNanos = mRrThrottleNanos[i];
1487 }
1488 }
1489
1490 DISPLAY_ATRACE_INT("RefreshRateDelayRequester", maxDelayRequester);
1491 DISPLAY_ATRACE_INT64("RefreshRateDelay", ns2ms(maxDelayNanos));
1492 if (mRefreshRateDelayNanos == maxDelayNanos) {
1493 return NO_ERROR;
1494 }
1495
1496 if (mVariableRefreshRateController) {
1497 int ret = mVariableRefreshRateController->setFixedRefreshRateRange(mMinIdleRefreshRate,
1498 maxDelayNanos);
1499 if (ret >= 0) {
1500 mRefreshRateDelayNanos = maxDelayNanos;
1501 return NO_ERROR;
1502 }
1503 return ret;
1504 }
1505
1506 ret = setDisplayIdleDelayNanos(maxDelayNanos, DispIdleTimerRequester::RR_THROTTLE);
1507 if (ret == NO_ERROR) {
1508 mRefreshRateDelayNanos = maxDelayNanos;
1509 }
1510 }
1511
1512 Mutex::Autolock lock(mDisplayMutex);
1513 if (ret == NO_ERROR) {
1514 recalculateTimelineLocked(maxDelayNanos);
1515 }
1516
1517 return ret;
1518 }
1519
dump(String8 & result,const std::vector<std::string> & args)1520 void ExynosPrimaryDisplay::dump(String8& result, const std::vector<std::string>& args) {
1521 ExynosDisplay::dump(result);
1522 result.appendFormat("Display idle timer: %s\n",
1523 (mDisplayIdleTimerEnabled) ? "enabled" : "disabled");
1524 for (uint32_t i = 0; i < toUnderlying(DispIdleTimerRequester::MAX); i++) {
1525 result.appendFormat("\t[%u] vote to %" PRId64 " ns\n", i, mDisplayIdleTimerNanos[i]);
1526 }
1527
1528 if (!mBrightnessBlockingZonesLookupTable.empty()) {
1529 int upperBound;
1530 int lowerBound = INT_MIN;
1531 result.appendFormat("Brightness blocking zone lookup table:\n");
1532 for (const auto& brightnessBlockingZone : mBrightnessBlockingZonesLookupTable) {
1533 upperBound = brightnessBlockingZone.first;
1534 result.appendFormat("\tBrightness blocking zone: range [%s %s) fps = %d\n",
1535 (lowerBound == INT_MIN ? "Min"
1536 : std::to_string(lowerBound).c_str()),
1537 (upperBound == INT_MAX ? "Max"
1538 : std::to_string(upperBound).c_str()),
1539 brightnessBlockingZone.second);
1540 lowerBound = upperBound;
1541 }
1542 } else {
1543 result.appendFormat("\n");
1544 }
1545
1546 result.appendFormat("Min idle refresh rate: %d\n", mMinIdleRefreshRate);
1547 for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
1548 result.appendFormat("\t[%u] vote to %d hz\n", i, mRrThrottleFps[i]);
1549 }
1550
1551 result.appendFormat("Refresh rate delay: %" PRId64 " ns\n", mRefreshRateDelayNanos);
1552 for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
1553 result.appendFormat("\t[%u] vote to %" PRId64 " ns\n", i, mRrThrottleNanos[i]);
1554 }
1555 if (mIsDisplayTempMonitorSupported) {
1556 result.appendFormat("Temperature : %d°C\n", mDisplayTemperature);
1557 }
1558 result.appendFormat("\n");
1559
1560 DisplayType displayType = getDcDisplayType();
1561 std::string displayTypeIdentifier;
1562 if (displayType == DisplayType::DISPLAY_PRIMARY) {
1563 displayTypeIdentifier = "primarydisplay";
1564 } else if (displayType == DisplayType::DISPLAY_EXTERNAL) {
1565 displayTypeIdentifier = "externaldisplay";
1566 }
1567 if (!displayTypeIdentifier.empty()) {
1568 auto xrrVersion =
1569 android::hardware::graphics::composer::getDisplayXrrVersion(displayTypeIdentifier);
1570 result.appendFormat("XRR version: %d.%d\n", xrrVersion.first, xrrVersion.second);
1571 }
1572 if (mVariableRefreshRateController) {
1573 mVariableRefreshRateController->dump(result, args);
1574 }
1575 }
1576
calculateTimelineLocked(hwc2_config_t config,hwc_vsync_period_change_constraints_t * vsyncPeriodChangeConstraints,hwc_vsync_period_change_timeline_t * outTimeline)1577 void ExynosPrimaryDisplay::calculateTimelineLocked(
1578 hwc2_config_t config, hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
1579 hwc_vsync_period_change_timeline_t* outTimeline) {
1580 ATRACE_CALL();
1581 int64_t desiredUpdateTimeNanos = vsyncPeriodChangeConstraints->desiredTimeNanos;
1582 const int64_t origDesiredUpdateTimeNanos = desiredUpdateTimeNanos;
1583 int64_t threshold = 0;
1584 int64_t lastUpdateDelta = 0;
1585 int64_t actualChangeTime = 0;
1586 bool isDelayed = false;
1587
1588 /* actualChangeTime includes transient duration */
1589 mDisplayInterface->getVsyncAppliedTime(config, &actualChangeTime);
1590
1591 outTimeline->refreshRequired = true;
1592
1593 /* When the refresh rate changes from high to low, check if RR throttle is needed */
1594 {
1595 std::lock_guard<std::mutex> lock(mIdleRefreshRateThrottleMutex);
1596 threshold = mRefreshRateDelayNanos;
1597 mRrUseDelayNanos = 0;
1598 mIsRrNeedCheckDelay = !mXrrSettings.versionInfo.needVrrParameters() &&
1599 mDisplayConfigs[mActiveConfig].vsyncPeriod < mDisplayConfigs[config].vsyncPeriod;
1600 if (threshold != 0 && mLastRefreshRateAppliedNanos != 0 && mIsRrNeedCheckDelay) {
1601 lastUpdateDelta = desiredUpdateTimeNanos - mLastRefreshRateAppliedNanos;
1602 if (lastUpdateDelta < threshold) {
1603 /* in this case, the active config change needs to be delayed */
1604 isDelayed = true;
1605 desiredUpdateTimeNanos += threshold - lastUpdateDelta;
1606 mRrUseDelayNanos = threshold;
1607 }
1608 }
1609 }
1610
1611 mVsyncPeriodChangeConstraints.desiredTimeNanos = desiredUpdateTimeNanos;
1612
1613 getConfigAppliedTime(mVsyncPeriodChangeConstraints.desiredTimeNanos, actualChangeTime,
1614 outTimeline->newVsyncAppliedTimeNanos, outTimeline->refreshTimeNanos);
1615
1616 const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
1617 DISPLAY_LOGD_AND_ATRACE_NAME(eDebugDisplayConfig,
1618 "requested config : %d(%d)->%d(%d), isDelay:%d,"
1619 " delta %" PRId64 ", delay %" PRId64 ", threshold %" PRId64 ", "
1620 "now:%" PRId64 ", desired %" PRId64 "->%" PRId64
1621 ", newVsyncAppliedTimeNanos : %" PRId64
1622 ", refreshTimeNanos:%" PRId64
1623 ", mLastRefreshRateAppliedNanos:%" PRId64,
1624 mActiveConfig, mDisplayConfigs[mActiveConfig].vsyncPeriod, config,
1625 mDisplayConfigs[config].vsyncPeriod, isDelayed,
1626 ns2ms(lastUpdateDelta), ns2ms(threshold - lastUpdateDelta),
1627 ns2ms(threshold), ns2ms(now), ns2ms(origDesiredUpdateTimeNanos),
1628 ns2ms(mVsyncPeriodChangeConstraints.desiredTimeNanos),
1629 ns2ms(outTimeline->newVsyncAppliedTimeNanos),
1630 ns2ms(outTimeline->refreshTimeNanos),
1631 ns2ms(mLastRefreshRateAppliedNanos));
1632
1633 DISPLAY_ATRACE_INT64("TimeToApplyConfig",
1634 ns2ms(mVsyncPeriodChangeConstraints.desiredTimeNanos - now));
1635 }
1636
recalculateTimelineLocked(int64_t refreshRateDelayNanos)1637 void ExynosPrimaryDisplay::recalculateTimelineLocked(int64_t refreshRateDelayNanos) {
1638 ATRACE_CALL();
1639
1640 if (mConfigRequestState != hwc_request_state_t::SET_CONFIG_STATE_PENDING) {
1641 return;
1642 }
1643
1644 std::lock_guard<std::mutex> lock(mIdleRefreshRateThrottleMutex);
1645 if (!mIsRrNeedCheckDelay) {
1646 return;
1647 }
1648
1649 int64_t desiredUpdateTimeNanos = mVsyncPeriodChangeConstraints.desiredTimeNanos;
1650 if (mRrUseDelayNanos) {
1651 desiredUpdateTimeNanos += (refreshRateDelayNanos - mRrUseDelayNanos);
1652 } else {
1653 int64_t lastUpdateDelta =
1654 mVsyncPeriodChangeConstraints.desiredTimeNanos - mLastRefreshRateAppliedNanos;
1655 if (lastUpdateDelta < refreshRateDelayNanos) {
1656 desiredUpdateTimeNanos += (refreshRateDelayNanos - lastUpdateDelta);
1657 }
1658 }
1659 mRrUseDelayNanos = refreshRateDelayNanos;
1660
1661 const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
1662 if (desiredUpdateTimeNanos > now) {
1663 mVsyncPeriodChangeConstraints.desiredTimeNanos = desiredUpdateTimeNanos;
1664 } else {
1665 mVsyncPeriodChangeConstraints.desiredTimeNanos = now;
1666 }
1667
1668 DISPLAY_ATRACE_INT64("TimeToApplyConfig",
1669 ns2ms(mVsyncPeriodChangeConstraints.desiredTimeNanos - now));
1670 }
1671
updateAppliedActiveConfig(const hwc2_config_t newConfig,const int64_t ts)1672 void ExynosPrimaryDisplay::updateAppliedActiveConfig(const hwc2_config_t newConfig,
1673 const int64_t ts) {
1674 ATRACE_CALL();
1675 if (mAppliedActiveConfig == 0 ||
1676 getDisplayVsyncPeriodFromConfig(mAppliedActiveConfig) !=
1677 getDisplayVsyncPeriodFromConfig(newConfig)) {
1678 DISPLAY_LOGD(eDebugDisplayConfig,
1679 "%s mAppliedActiveConfig(%d->%d), mLastRefreshRateAppliedNanos(%" PRIu64
1680 " -> %" PRIu64 ")",
1681 __func__, mAppliedActiveConfig, newConfig, mLastRefreshRateAppliedNanos, ts);
1682 mLastRefreshRateAppliedNanos = ts;
1683 DISPLAY_ATRACE_INT64("LastRefreshRateAppliedMs", ns2ms(mLastRefreshRateAppliedNanos));
1684 }
1685
1686 mAppliedActiveConfig = newConfig;
1687 }
1688
checkBtsReassignResource(const int32_t vsyncPeriod,const int32_t btsVsyncPeriod)1689 void ExynosPrimaryDisplay::checkBtsReassignResource(const int32_t vsyncPeriod,
1690 const int32_t btsVsyncPeriod) {
1691 ATRACE_CALL();
1692 uint32_t refreshRate = static_cast<uint32_t>(round(nsecsPerSec / vsyncPeriod * 0.1f) * 10);
1693
1694 Mutex::Autolock lock(mDRMutex);
1695 if (vsyncPeriod < btsVsyncPeriod) {
1696 for (size_t i = 0; i < mLayers.size(); i++) {
1697 if (mLayers[i]->mOtfMPP && mLayers[i]->mM2mMPP == nullptr &&
1698 !mLayers[i]->checkBtsCap(refreshRate)) {
1699 mLayers[i]->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
1700 break;
1701 }
1702 }
1703 } else if (vsyncPeriod > btsVsyncPeriod) {
1704 for (size_t i = 0; i < mLayers.size(); i++) {
1705 if (mLayers[i]->mOtfMPP && mLayers[i]->mM2mMPP) {
1706 float srcWidth = mLayers[i]->mSourceCrop.right - mLayers[i]->mSourceCrop.left;
1707 float srcHeight = mLayers[i]->mSourceCrop.bottom - mLayers[i]->mSourceCrop.top;
1708 float resolution = srcWidth * srcHeight * refreshRate / 1000;
1709 float ratioVertical = static_cast<float>(mLayers[i]->mDisplayFrame.bottom -
1710 mLayers[i]->mDisplayFrame.top) /
1711 mYres;
1712
1713 if (mLayers[i]->mOtfMPP->checkDownscaleCap(resolution, ratioVertical)) {
1714 mLayers[i]->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
1715 break;
1716 }
1717 }
1718 }
1719 }
1720 }
1721
isDbmSupported()1722 bool ExynosPrimaryDisplay::isDbmSupported() {
1723 return mBrightnessController->isDbmSupported();
1724 }
1725
setDbmState(bool enabled)1726 int32_t ExynosPrimaryDisplay::setDbmState(bool enabled) {
1727 mBrightnessController->processDimBrightness(enabled);
1728 return NO_ERROR;
1729 }
1730
getRefreshListener()1731 RefreshListener* ExynosPrimaryDisplay::getRefreshListener() {
1732 if (mVariableRefreshRateController) {
1733 return mVariableRefreshRateController.get();
1734 }
1735 return nullptr;
1736 }
1737
getVsyncListener()1738 VsyncListener* ExynosPrimaryDisplay::getVsyncListener() {
1739 if (mVariableRefreshRateController) {
1740 return mVariableRefreshRateController.get();
1741 }
1742 return nullptr;
1743 }
1744
onConfigChange(int configId)1745 void ExynosPrimaryDisplay::onConfigChange(int configId) {
1746 if (mVariableRefreshRateController) {
1747 return mVariableRefreshRateController->setActiveVrrConfiguration(configId);
1748 }
1749 }
1750
getPanelName()1751 const std::string& ExynosPrimaryDisplay::getPanelName() {
1752 if (!mPanelName.empty()) {
1753 return mPanelName;
1754 }
1755
1756 const std::string& sysfs = getPanelSysfsPath();
1757 if (!sysfs.empty()) {
1758 std::string sysfs_rel("panel_name");
1759 if (readLineFromFile(sysfs + "/" + sysfs_rel, mPanelName, '\n') != OK) {
1760 ALOGE("failed reading %s/%s", sysfs.c_str(), sysfs_rel.c_str());
1761 }
1762 }
1763 return mPanelName;
1764 }
1765
registerRefreshRateChangeListener(std::shared_ptr<RefreshRateChangeListener> listener)1766 int32_t ExynosPrimaryDisplay::registerRefreshRateChangeListener(
1767 std::shared_ptr<RefreshRateChangeListener> listener) {
1768 if (!mXrrSettings.versionInfo.hasVrrController()) return HWC2_ERROR_UNSUPPORTED;
1769
1770 if (mVariableRefreshRateController) {
1771 mVariableRefreshRateController->registerRefreshRateChangeListener(listener);
1772 return NO_ERROR;
1773 } else {
1774 return -EINVAL;
1775 }
1776 }
1777
1778 // TODO(b/355579338): to create a dedicated class DisplayTemperatureMonitor
initDisplayTempMonitor(const std::string & display)1779 bool ExynosPrimaryDisplay::initDisplayTempMonitor(const std::string& display) {
1780 mDisplayTempInterval = property_get_int32(kDisplayTempIntervalSec, 0);
1781
1782 if (mDisplayTempInterval <= 0) {
1783 ALOGD("%s: Invalid display temperature interval: %d", __func__, mDisplayTempInterval);
1784 return false;
1785 }
1786
1787 auto propertyName = getPropertyDisplayTemperatureStr(display);
1788
1789 char value[PROPERTY_VALUE_MAX];
1790 auto ret = property_get(propertyName.c_str(), value, "");
1791
1792 if (ret <= 0) {
1793 ALOGD("%s: Display temperature property values is empty", __func__);
1794 return false;
1795 }
1796
1797 mDisplayTempSysfsNode = String8(value);
1798 return true;
1799 }
1800
getDisplayTemperature()1801 int32_t ExynosPrimaryDisplay::getDisplayTemperature() {
1802 DISPLAY_ATRACE_CALL();
1803
1804 if (mDisplayTempSysfsNode.empty()) {
1805 ALOGE("%s: Display temp sysfs node string is empty", __func__);
1806 return UINT_MAX;
1807 }
1808
1809 int32_t temperature;
1810 std::ifstream ifs(mDisplayTempSysfsNode.c_str());
1811
1812 if (!ifs.is_open()) {
1813 ALOGE("%s: Unable to open node '%s', error = %s", __func__, mDisplayTempSysfsNode.c_str(),
1814 strerror(errno));
1815 return UINT_MAX;
1816 }
1817
1818 if (!(ifs >> temperature) || !ifs.good()) {
1819 ALOGE("%s: Unable to read node '%s', error = %s", __func__, mDisplayTempSysfsNode.c_str(),
1820 strerror(errno));
1821 }
1822
1823 ifs.close();
1824 return temperature / 1000;
1825 }
1826
isTemperatureMonitorThreadRunning()1827 bool ExynosPrimaryDisplay::isTemperatureMonitorThreadRunning() {
1828 android_atomic_acquire_load(&mTMThreadStatus);
1829 return (mTMThreadStatus > 0);
1830 }
1831
checkTemperatureMonitorThread(bool shouldRun)1832 void ExynosPrimaryDisplay::checkTemperatureMonitorThread(bool shouldRun) {
1833 ATRACE_CALL();
1834 if (!mIsDisplayTempMonitorSupported) {
1835 return;
1836 }
1837
1838 // If thread was destroyed, create thread and run.
1839 if (!isTemperatureMonitorThreadRunning()) {
1840 if (shouldRun) {
1841 temperatureMonitorThreadCreate();
1842 return;
1843 }
1844 } else {
1845 // if screen state changed make the thread suspend/resume.
1846 {
1847 std::lock_guard<std::mutex> lock(mThreadMutex);
1848 if (mTMLoopStatus != shouldRun) {
1849 mTMLoopStatus = shouldRun;
1850 mTMCondition.notify_one();
1851 }
1852 }
1853 }
1854 }
1855
temperatureMonitorThreadCreate()1856 void ExynosPrimaryDisplay::temperatureMonitorThreadCreate() {
1857 mTMLoopStatus.store(false, std::memory_order_relaxed);
1858
1859 ALOGI("Creating monitor display temperature thread");
1860 mTMLoopStatus.store(true, std::memory_order_relaxed);
1861 mTMThread = std::thread(&ExynosPrimaryDisplay::temperatureMonitorThreadLoop, this);
1862 mTMCondition.notify_one();
1863 }
1864
temperatureMonitorThreadLoop()1865 void* ExynosPrimaryDisplay::temperatureMonitorThreadLoop() {
1866 android_atomic_inc(&mTMThreadStatus);
1867 while (true) {
1868 std::unique_lock<std::mutex> lock(mThreadMutex);
1869 mTMCondition.wait(lock, [this] { return mTMLoopStatus.load(std::memory_order_relaxed); });
1870
1871 mDisplayTemperature = getDisplayTemperature();
1872 if (mDisplayTemperature == UINT_MAX) {
1873 ALOGE("%s: Failed to get display temperature", LOG_TAG);
1874 } else {
1875 ALOGI("Display Temperature : %d°C", mDisplayTemperature);
1876 }
1877
1878 // Wait for the specified interval or until the thread is suspended
1879 mTMCondition.wait_for(lock, std::chrono::seconds(mDisplayTempInterval),
1880 [this] { return !mTMLoopStatus.load(std::memory_order_relaxed); });
1881 }
1882 android_atomic_dec(&mTMThreadStatus);
1883 return NULL;
1884 }
1885