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->WriteUint32(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 }
248
249 // Allow to enable dynamic recomposition after every power on
250 // since it will always be disabled for every power off
251 // TODO(b/268474771): to enable DR by default if video mode panel is detected
252 if (property_get_int32("vendor.display.dynamic_recomposition", 0) & (1 << index)) {
253 mDRDefault = true;
254 mDREnable = true;
255 }
256
257 // Prepare multi resolution
258 // Will be exynosHWCControl.multiResoultion
259 mResolutionInfo.nNum = 1;
260 mResolutionInfo.nResolution[0].w = 1440;
261 mResolutionInfo.nResolution[0].h = 2960;
262 mResolutionInfo.nDSCYSliceSize[0] = 40;
263 mResolutionInfo.nDSCXSliceSize[0] = 1440 / 2;
264 mResolutionInfo.nPanelType[0] = PANEL_DSC;
265 mResolutionInfo.nResolution[1].w = 1080;
266 mResolutionInfo.nResolution[1].h = 2220;
267 mResolutionInfo.nDSCYSliceSize[1] = 30;
268 mResolutionInfo.nDSCXSliceSize[1] = 1080 / 2;
269 mResolutionInfo.nPanelType[1] = PANEL_DSC;
270 mResolutionInfo.nResolution[2].w = 720;
271 mResolutionInfo.nResolution[2].h = 1480;
272 mResolutionInfo.nDSCYSliceSize[2] = 74;
273 mResolutionInfo.nDSCXSliceSize[2] = 720;
274 mResolutionInfo.nPanelType[2] = PANEL_LEGACY;
275
276 char value[PROPERTY_VALUE_MAX];
277 const char *earlyWakeupNodeBase = early_wakeup_node_0_base;
278 if (getDcDisplayType() == DisplayType::DISPLAY_SECONDARY &&
279 property_get("vendor.display.secondary_early_wakeup_node", value, "") > 0) {
280 earlyWakeupNodeBase = value;
281 }
282 mEarlyWakeupDispFd = fopen(earlyWakeupNodeBase, "w");
283 if (mEarlyWakeupDispFd == nullptr)
284 ALOGE("open %s failed! %s", earlyWakeupNodeBase, strerror(errno));
285 mBrightnessController = std::make_unique<BrightnessController>(
__anon3d44092b0202() 286 mIndex, [this]() { mDevice->onRefresh(mDisplayId); },
__anon3d44092b0302() 287 [this]() { updatePresentColorConversionInfo(); });
288 mHistogramController = std::make_unique<HistogramController>(this);
289
290 mDisplayControl.multiThreadedPresent = true;
291
292 int fixedTe2DefaultRateHz =
293 property_get_int32("vendor.primarydisplay.fixed_te2.default_rate_hz", 0);
294 if (fixedTe2DefaultRateHz) {
295 mDisplayTe2Manager =
296 std::make_unique<DisplayTe2Manager>(this, mIndex, fixedTe2DefaultRateHz);
297 }
298 }
299
~ExynosPrimaryDisplay()300 ExynosPrimaryDisplay::~ExynosPrimaryDisplay()
301 {
302 if (mEarlyWakeupDispFd) {
303 fclose(mEarlyWakeupDispFd);
304 mEarlyWakeupDispFd = nullptr;
305 }
306
307 if (mDisplayNeedHandleIdleExitOfs.is_open()) {
308 mDisplayNeedHandleIdleExitOfs.close();
309 }
310 }
311
setDDIScalerEnable(int width,int height)312 void ExynosPrimaryDisplay::setDDIScalerEnable(int width, int height) {
313
314 if (exynosHWCControl.setDDIScaler == false) return;
315
316 ALOGI("DDISCALER Info : setDDIScalerEnable(w=%d,h=%d)", width, height);
317 mNewScaledWidth = width;
318 mNewScaledHeight = height;
319 mXres = width;
320 mYres = height;
321 }
322
getDDIScalerMode(int width,int height)323 int ExynosPrimaryDisplay::getDDIScalerMode(int width, int height) {
324
325 if (exynosHWCControl.setDDIScaler == false) return 1;
326
327 // Check if panel support support resolution or not.
328 for (uint32_t i=0; i < mResolutionInfo.nNum; i++) {
329 if (mResolutionInfo.nResolution[i].w * mResolutionInfo.nResolution[i].h ==
330 static_cast<uint32_t>(width * height))
331 return i + 1;
332 }
333
334 return 1; // WQHD
335 }
336
doDisplayConfigInternal(hwc2_config_t config)337 int32_t ExynosPrimaryDisplay::doDisplayConfigInternal(hwc2_config_t config) {
338 if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON) ||
339 !isConfigSettingEnabled()) {
340 mPendingConfig = config;
341 mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_DONE;
342 DISPLAY_LOGI("%s:: Pending desired Config: %d", __func__, config);
343 return NO_ERROR;
344 }
345 return ExynosDisplay::doDisplayConfigInternal(config);
346 }
347
getActiveConfigInternal(hwc2_config_t * outConfig)348 int32_t ExynosPrimaryDisplay::getActiveConfigInternal(hwc2_config_t *outConfig) {
349 if (outConfig && mPendingConfig != UINT_MAX) {
350 *outConfig = mPendingConfig;
351 return HWC2_ERROR_NONE;
352 }
353 return ExynosDisplay::getActiveConfigInternal(outConfig);
354 }
355
setActiveConfigInternal(hwc2_config_t config,bool force)356 int32_t ExynosPrimaryDisplay::setActiveConfigInternal(hwc2_config_t config, bool force) {
357 hwc2_config_t cur_config;
358
359 getActiveConfigInternal(&cur_config);
360 if (cur_config == config) {
361 ALOGI("%s:: Same display config is set", __func__);
362 return HWC2_ERROR_NONE;
363 }
364 if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON) ||
365 !isConfigSettingEnabled()) {
366 mPendingConfig = config;
367 return HWC2_ERROR_NONE;
368 }
369 return ExynosDisplay::setActiveConfigInternal(config, force);
370 }
371
372 // If a display is Off, applyPendingConfig() calls to setActiveConfig() that also
373 // power on the display by a blocking commit.
applyPendingConfig()374 int32_t ExynosPrimaryDisplay::applyPendingConfig() {
375 if (!isConfigSettingEnabled()) {
376 ALOGI("%s:: config setting is disabled", __func__);
377 if (mPowerModeState.has_value() && (*mPowerModeState == HWC2_POWER_MODE_ON)) {
378 ALOGI("%s:: skip apply pending config", __func__);
379 return HWC2_ERROR_NONE;
380 }
381 }
382
383 hwc2_config_t config;
384 if (mPendingConfig != UINT_MAX) {
385 ALOGI("%s:: mPendingConfig: %d", __func__, mPendingConfig);
386 config = mPendingConfig;
387 mPendingConfig = UINT_MAX;
388 } else {
389 getActiveConfigInternal(&config);
390 }
391
392 return ExynosDisplay::setActiveConfigInternal(config, true);
393 }
394
setBootDisplayConfig(int32_t config)395 int32_t ExynosPrimaryDisplay::setBootDisplayConfig(int32_t config) {
396 auto hwcConfig = static_cast<hwc2_config_t>(config);
397
398 const auto &it = mDisplayConfigs.find(hwcConfig);
399 if (it == mDisplayConfigs.end()) {
400 DISPLAY_LOGE("%s: invalid config %d", __func__, config);
401 return HWC2_ERROR_BAD_CONFIG;
402 }
403
404 const auto &mode = it->second;
405 if (mode.vsyncPeriod == 0)
406 return HWC2_ERROR_BAD_CONFIG;
407
408 char modeStr[PROPERTY_VALUE_MAX];
409 int ret = snprintf(modeStr, sizeof(modeStr), "%dx%d@%d:%d", mode.width, mode.height,
410 mode.refreshRate, nanoSec2Hz(mode.vsyncPeriod));
411 if (ret <= 0)
412 return HWC2_ERROR_BAD_CONFIG;
413
414 ALOGD("%s: mode=%s (%d)", __func__, modeStr, config);
415 ret = property_set(getPropertyBootModeStr(mDisplayId).c_str(), modeStr);
416
417 return !ret ? HWC2_ERROR_NONE : HWC2_ERROR_BAD_CONFIG;
418 }
419
clearBootDisplayConfig()420 int32_t ExynosPrimaryDisplay::clearBootDisplayConfig() {
421 auto ret = property_set(getPropertyBootModeStr(mDisplayId).c_str(), nullptr);
422
423 ALOGD("%s: clearing boot mode", __func__);
424 return !ret ? HWC2_ERROR_NONE : HWC2_ERROR_BAD_CONFIG;
425 }
426
getPreferredDisplayConfigInternal(int32_t * outConfig)427 int32_t ExynosPrimaryDisplay::getPreferredDisplayConfigInternal(int32_t *outConfig) {
428 char modeStr[PROPERTY_VALUE_MAX];
429 auto ret = property_get(getPropertyBootModeStr(mDisplayId).c_str(), modeStr, "");
430
431 if (ret <= 0) {
432 return mDisplayInterface->getDefaultModeId(outConfig);
433 }
434
435 int width, height;
436 int fps = 0, vsyncRate = 0;
437
438 ret = sscanf(modeStr, "%dx%d@%d:%d", &width, &height, &fps, &vsyncRate);
439 if (ret < 4) {
440 ret = sscanf(modeStr, "%dx%d@%d", &width, &height, &fps);
441 if ((ret < 3) || !fps) {
442 ALOGW("%s: unable to find boot config for mode: %s", __func__, modeStr);
443 return HWC2_ERROR_BAD_CONFIG;
444 }
445 if (lookupDisplayConfigs(width, height, fps, fps, outConfig) != HWC2_ERROR_NONE) {
446 ALOGE("%s: kernel doesn't support mode: %s", __func__, modeStr);
447 return HWC2_ERROR_BAD_CONFIG;
448 }
449 ret = setBootDisplayConfig(*outConfig);
450 if (ret == HWC2_ERROR_NONE)
451 ALOGI("%s: succeeded to replace %s with new format", __func__, modeStr);
452 else
453 ALOGE("%s: failed to replace %s with new format", __func__, modeStr);
454 return ret;
455 }
456 if (!fps || !vsyncRate || (fps > vsyncRate)) {
457 ALOGE("%s: bad boot config: %s", __func__, modeStr);
458 return HWC2_ERROR_BAD_CONFIG;
459 }
460 return lookupDisplayConfigs(width, height, fps, vsyncRate, outConfig);
461 }
462
setPowerOn()463 int32_t ExynosPrimaryDisplay::setPowerOn() {
464 ATRACE_CALL();
465 updateAppliedActiveConfig(0, 0);
466 int ret = NO_ERROR;
467 if (mDisplayId != 0 || !mFirstPowerOn) {
468 if (mDevice->hasOtherDisplayOn(this)) {
469 mResourceManager->prepareResources(mDisplayId);
470 // TODO: This is useful for cmd mode, and b/282094671 tries to handles video mode
471 mDisplayInterface->triggerClearDisplayPlanes();
472 }
473 ret = applyPendingConfig();
474 }
475
476 if (!mPowerModeState.has_value() || (*mPowerModeState == HWC2_POWER_MODE_OFF)) {
477 // check the dynamic recomposition thread by following display
478 mDevice->checkDynamicRecompositionThread();
479 if (ret) {
480 mDisplayInterface->setPowerMode(HWC2_POWER_MODE_ON);
481 }
482 setGeometryChanged(GEOMETRY_DISPLAY_POWER_ON);
483 }
484
485 {
486 std::lock_guard<std::mutex> lock(mPowerModeMutex);
487 mPowerModeState = HWC2_POWER_MODE_ON;
488 if (mNotifyPowerOn) {
489 mPowerOnCondition.notify_one();
490 mNotifyPowerOn = false;
491 }
492 }
493
494 if (mDisplayTe2Manager) mDisplayTe2Manager->restoreTe2FromDozeMode();
495
496 if (mFirstPowerOn) {
497 firstPowerOn();
498 }
499
500 return HWC2_ERROR_NONE;
501 }
502
setPowerOff()503 int32_t ExynosPrimaryDisplay::setPowerOff() {
504 ATRACE_CALL();
505
506 clearDisplay(true);
507
508 // check the dynamic recomposition thread by following display
509 mDevice->checkDynamicRecompositionThread();
510
511 mDisplayInterface->setPowerMode(HWC2_POWER_MODE_OFF);
512
513 {
514 std::lock_guard<std::mutex> lock(mPowerModeMutex);
515 mPowerModeState = HWC2_POWER_MODE_OFF;
516 }
517
518 /* It should be called from validate() when the screen is on */
519 mSkipFrame = true;
520 setGeometryChanged(GEOMETRY_DISPLAY_POWER_OFF);
521 if ((mRenderingState >= RENDERING_STATE_VALIDATED) &&
522 (mRenderingState < RENDERING_STATE_PRESENTED))
523 closeFencesForSkipFrame(RENDERING_STATE_VALIDATED);
524 mRenderingState = RENDERING_STATE_NONE;
525
526 // in the case user turns off screen when LHBM is on
527 // TODO: b/236433238 considering a lock for mLhbmOn state
528 mLhbmOn = false;
529 return HWC2_ERROR_NONE;
530 }
531
setPowerDoze(hwc2_power_mode_t mode)532 int32_t ExynosPrimaryDisplay::setPowerDoze(hwc2_power_mode_t mode) {
533 ATRACE_CALL();
534
535 if (!mDisplayInterface->isDozeModeAvailable()) {
536 return HWC2_ERROR_UNSUPPORTED;
537 }
538
539 if (mPowerModeState.has_value() &&
540 ((*mPowerModeState == HWC2_POWER_MODE_OFF) || (*mPowerModeState == HWC2_POWER_MODE_ON))) {
541 if (mDisplayInterface->setLowPowerMode()) {
542 ALOGI("Not support LP mode.");
543 return HWC2_ERROR_UNSUPPORTED;
544 }
545 }
546
547 {
548 std::lock_guard<std::mutex> lock(mPowerModeMutex);
549 mPowerModeState = mode;
550 }
551
552 // LHBM will be disabled in the kernel while entering AOD mode if it's
553 // already enabled. Reset the state to avoid the sync problem.
554 mBrightnessController->resetLhbmState();
555 mLhbmOn = false;
556
557 ExynosDisplay::updateRefreshRateHint();
558
559 if (mDisplayTe2Manager) mDisplayTe2Manager->updateTe2ForDozeMode();
560
561 return HWC2_ERROR_NONE;
562 }
563
setPowerMode(int32_t mode)564 int32_t ExynosPrimaryDisplay::setPowerMode(int32_t mode) {
565 Mutex::Autolock lock(mDisplayMutex);
566
567 if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::PAUSE)) {
568 mode = HWC2_POWER_MODE_OFF;
569 mPauseDisplay = true;
570 } else if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME)) {
571 mode = HWC2_POWER_MODE_ON;
572 mPauseDisplay = false;
573 } else if (mPauseDisplay) {
574 ALOGI("Skip power mode transition due to pause display.");
575 return HWC2_ERROR_NONE;
576 }
577
578 if (mPowerModeState.has_value() && (mode == static_cast<int32_t>(mPowerModeState.value()))) {
579 ALOGI("Skip power mode transition due to the same power state.");
580 return HWC2_ERROR_NONE;
581 }
582
583 if (mode == HWC2_POWER_MODE_ON && mDevice->mNumPrimaryDisplays >= 2) {
584 ExynosDisplay* external_display =
585 mDevice->getDisplay(getDisplayId(HWC_DISPLAY_EXTERNAL, 0));
586 ExynosDisplayDrmInterface* external_display_intf = external_display
587 ? static_cast<ExynosDisplayDrmInterface*>(external_display->mDisplayInterface.get())
588 : nullptr;
589 if (external_display_intf && external_display_intf->borrowedCrtcFrom() == this) {
590 ALOGI("Display %s is powering on, adjusting decon assignments",
591 mDisplayTraceName.c_str());
592 hwc2_config_t activeConfig = 0;
593 external_display->getActiveConfig(&activeConfig);
594 external_display->clearDisplay(true);
595 external_display->setPowerMode(HWC2_POWER_MODE_OFF);
596 // Restore the original decon assigned to external display, this will ensure
597 // primary displays remain on the same initially assigned decons.
598 external_display_intf->swapCrtcs(this);
599 // This display is about to be powered on, but its mPowerModeState is not updated yet,
600 // so we need to exclude it from consideration explicitly here.
601 ExynosDisplay* poweredOffPrimaryDisplay = mDevice->findPoweredOffPrimaryDisplay(this);
602 if (poweredOffPrimaryDisplay) {
603 ALOGI("Found powered off primary display %s, will use its decon for external "
604 "display",
605 poweredOffPrimaryDisplay->mDisplayTraceName.c_str());
606 external_display_intf->swapCrtcs(poweredOffPrimaryDisplay);
607 } else {
608 ALOGE("Could not find a powered off primary display!");
609 }
610 external_display->mActiveConfig = 0;
611 external_display->setActiveConfig(activeConfig);
612 external_display->setPowerMode(HWC2_POWER_MODE_ON);
613 }
614 }
615
616 int fb_blank = (mode != HWC2_POWER_MODE_OFF) ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
617 ALOGD("%s:: FBIOBLANK mode(%d), blank(%d)", __func__, mode, fb_blank);
618
619 if (fb_blank == FB_BLANK_POWERDOWN)
620 mDREnable = false;
621 else
622 mDREnable = mDRDefault;
623
624 if (mOperationRateManager) {
625 mOperationRateManager->onPowerMode(mode);
626 mBrightnessController->processOperationRate(
627 mOperationRateManager->getTargetOperationRate());
628 }
629
630 std::lock_guard<std::mutex> minIdleRefreshRateLock(mMinIdleRefreshRateMutex);
631 if (mVariableRefreshRateController) {
632 if ((mode == HWC2_POWER_MODE_DOZE) || (mode == HWC2_POWER_MODE_DOZE_SUSPEND)) {
633 mVariableRefreshRateController->setFixedRefreshRateRange(kMinIdleRefreshRateForDozeMode,
634 0);
635 }
636 mVariableRefreshRateController->preSetPowerMode(mode);
637 }
638
639 int32_t res = HWC2_ERROR_BAD_PARAMETER;
640 switch (mode) {
641 case HWC2_POWER_MODE_DOZE:
642 case HWC2_POWER_MODE_DOZE_SUSPEND: {
643 if (mode == HWC2_POWER_MODE_DOZE && mDisplayInterface->needRefreshOnLP()) {
644 ALOGI("Refresh before setting power doze.");
645 mDevice->onRefresh(mDisplayId);
646 }
647 res = setPowerDoze(static_cast<hwc2_power_mode_t>(mode));
648 break;
649 }
650 case HWC2_POWER_MODE_OFF:
651 res = setPowerOff();
652 break;
653 case HWC2_POWER_MODE_ON:
654 res = setPowerOn();
655 break;
656 default:
657 return res;
658 }
659 if (res != HWC2_ERROR_NONE) {
660 return res;
661 }
662
663 ExynosDisplay::updateRefreshRateHint();
664 if (mVariableRefreshRateController) {
665 mVariableRefreshRateController->postSetPowerMode(mode);
666 if (mode == HWC2_POWER_MODE_ON) {
667 mVariableRefreshRateController->setFixedRefreshRateRange(mMinIdleRefreshRate,
668 mRefreshRateDelayNanos);
669 }
670 }
671 return res;
672 }
673
firstPowerOn()674 void ExynosPrimaryDisplay::firstPowerOn() {
675 SetCurrentPanelGammaSource(DisplayType::DISPLAY_PRIMARY, PanelGammaSource::GAMMA_CALIBRATION);
676 mFirstPowerOn = false;
677 getDisplayIdleTimerEnabled(mDisplayIdleTimerEnabled);
678 initDisplayHandleIdleExit();
679 }
680
getHDRException(ExynosLayer * __unused layer)681 bool ExynosPrimaryDisplay::getHDRException(ExynosLayer* __unused layer)
682 {
683 return false;
684 }
685
initDisplayInterface(uint32_t interfaceType)686 void ExynosPrimaryDisplay::initDisplayInterface(uint32_t interfaceType)
687 {
688 if (interfaceType == INTERFACE_TYPE_DRM)
689 mDisplayInterface = std::make_unique<ExynosPrimaryDisplayDrmInterfaceModule>((ExynosDisplay *)this);
690 else
691 LOG_ALWAYS_FATAL("%s::Unknown interface type(%d)",
692 __func__, interfaceType);
693 mDisplayInterface->init(this);
694
695 if (mXrrSettings.versionInfo.needVrrParameters()) {
696 mDisplayInterface->setXrrSettings(mXrrSettings);
697 }
698
699 mDpuData.init(mMaxWindowNum, mDevice->getSpecialPlaneNum(mDisplayId));
700 mLastDpuData.init(mMaxWindowNum, mDevice->getSpecialPlaneNum(mDisplayId));
701 ALOGI("window configs size(%zu) rcd configs zie(%zu)", mDpuData.configs.size(),
702 mDpuData.rcdConfigs.size());
703 }
704
getPanelSysfsPath(const DisplayType & type) const705 std::string ExynosPrimaryDisplay::getPanelSysfsPath(const DisplayType& type) const {
706 if ((type < DisplayType::DISPLAY_PRIMARY) || (type >= DisplayType::DISPLAY_MAX)) {
707 ALOGE("Invalid display panel type %d", type);
708 return {};
709 }
710
711 const auto& iter = panelSysfsPath.find(type);
712 if (iter == panelSysfsPath.end()) {
713 return {};
714 }
715
716 return iter->second;
717 }
718
SetCurrentPanelGammaSource(const DisplayType type,const PanelGammaSource & source)719 int32_t ExynosPrimaryDisplay::SetCurrentPanelGammaSource(const DisplayType type,
720 const PanelGammaSource &source) {
721 std::string &&panel_sysfs_path = getPanelSysfsPath(type);
722 if (panel_sysfs_path.empty()) {
723 return HWC2_ERROR_UNSUPPORTED;
724 }
725
726 std::ifstream ifs;
727 std::string &&path = panel_sysfs_path + "panel_name";
728 ifs.open(path, std::ifstream::in);
729 if (!ifs.is_open()) {
730 ALOGW("Unable to access panel name path '%s' (%s)", path.c_str(), strerror(errno));
731 return HWC2_ERROR_UNSUPPORTED;
732 }
733 std::string panel_name;
734 std::getline(ifs, panel_name);
735 ifs.close();
736
737 path = panel_sysfs_path + "serial_number";
738 ifs.open(path, std::ifstream::in);
739 if (!ifs.is_open()) {
740 ALOGW("Unable to access panel id path '%s' (%s)", path.c_str(), strerror(errno));
741 return HWC2_ERROR_UNSUPPORTED;
742 }
743 std::string panel_id;
744 std::getline(ifs, panel_id);
745 ifs.close();
746
747 std::string gamma_node = panel_sysfs_path + "gamma";
748 if (access(gamma_node.c_str(), W_OK)) {
749 ALOGW("Unable to access panel gamma calibration node '%s' (%s)", gamma_node.c_str(),
750 strerror(errno));
751 return HWC2_ERROR_UNSUPPORTED;
752 }
753
754 std::string &&gamma_data = "default";
755 if (source == PanelGammaSource::GAMMA_CALIBRATION) {
756 std::string gamma_cal_file(kDisplayCalFilePath);
757 gamma_cal_file.append(kPanelGammaCalFilePrefix)
758 .append(1, '_')
759 .append(panel_name)
760 .append(1, '_')
761 .append(panel_id)
762 .append(".cal");
763 if (access(gamma_cal_file.c_str(), R_OK)) {
764 ALOGI("Fail to access `%s` (%s), try golden gamma calibration", gamma_cal_file.c_str(),
765 strerror(errno));
766 gamma_cal_file = kDisplayCalFilePath;
767 gamma_cal_file.append(kPanelGammaCalFilePrefix)
768 .append(1, '_')
769 .append(panel_name)
770 .append(".cal");
771 }
772 gamma_data = loadPanelGammaCalibration(gamma_cal_file);
773 }
774
775 if (gamma_data.empty()) {
776 return HWC2_ERROR_UNSUPPORTED;
777 }
778
779 std::ofstream ofs(gamma_node);
780 if (!ofs.is_open()) {
781 ALOGW("Unable to open gamma node '%s', error = %s", gamma_node.c_str(), strerror(errno));
782 return HWC2_ERROR_UNSUPPORTED;
783 }
784 ofs.write(gamma_data.c_str(), gamma_data.size());
785 ofs.close();
786
787 currentPanelGammaSource = source;
788 return HWC2_ERROR_NONE;
789 }
790
isLhbmSupported()791 bool ExynosPrimaryDisplay::isLhbmSupported() {
792 return mBrightnessController->isLhbmSupported();
793 }
794
isConfigSettingEnabled()795 bool ExynosPrimaryDisplay::isConfigSettingEnabled() {
796 int64_t msSinceDisabled =
797 (systemTime(SYSTEM_TIME_MONOTONIC) - mConfigSettingDisabledTimestamp) / 1000000;
798 return !mConfigSettingDisabled || msSinceDisabled > kConfigDisablingMaxDurationMs;
799 }
800
enableConfigSetting(bool en)801 void ExynosPrimaryDisplay::enableConfigSetting(bool en) {
802 DISPLAY_ATRACE_INT("ConfigSettingDisabled", !en);
803 ALOGI("%s:: mConfigSettingDisabled: %d", __func__, !en);
804 if (!en) {
805 mConfigSettingDisabled = true;
806 mConfigSettingDisabledTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
807 return;
808 }
809
810 mConfigSettingDisabled = false;
811 }
812
getDisplayConfigs(uint32_t * outNumConfigs,hwc2_config_t * outConfigs)813 int32_t ExynosPrimaryDisplay::getDisplayConfigs(uint32_t* outNumConfigs,
814 hwc2_config_t* outConfigs) {
815 int32_t ret = ExynosDisplay::getDisplayConfigs(outNumConfigs, outConfigs);
816 if (ret == HWC2_ERROR_NONE) {
817 if (mXrrSettings.versionInfo.hasVrrController() && mDisplayConfigs.size()) {
818 if (!mVariableRefreshRateController) {
819 mVariableRefreshRateController =
820 VariableRefreshRateController::CreateInstance(this, getPanelName());
821 std::unordered_map<hwc2_config_t, VrrConfig_t> vrrConfigs;
822 for (const auto& it : mDisplayConfigs) {
823 if (!it.second.vrrConfig.has_value()) {
824 ALOGE("Both pseudo and full VRR modes should include VRR configurations.");
825 return HWC2_ERROR_BAD_CONFIG;
826 }
827 vrrConfigs[it.first] = it.second.vrrConfig.value();
828 }
829 mVariableRefreshRateController->setVrrConfigurations(std::move(vrrConfigs));
830 hwc2_config_t activeConfig;
831 if (ExynosDisplay::getActiveConfig(&activeConfig) == HWC2_ERROR_NONE) {
832 mVariableRefreshRateController->setActiveVrrConfiguration(activeConfig);
833 mVariableRefreshRateController->setEnable(true);
834 }
835 }
836 }
837 }
838 return ret;
839 }
840
presentDisplay(int32_t * outRetireFence)841 int32_t ExynosPrimaryDisplay::presentDisplay(int32_t* outRetireFence) {
842 auto res = ExynosDisplay::presentDisplay(outRetireFence);
843 // Forward presentDisplay if there is a listener.
844 const auto presentListener = getPresentListener();
845 if (res == HWC2_ERROR_NONE && presentListener) {
846 presentListener->onPresent(*outRetireFence);
847 }
848 return res;
849 }
850
onVsync(int64_t timestamp)851 void ExynosPrimaryDisplay::onVsync(int64_t timestamp) {
852 const auto vsyncListener = getVsyncListener();
853 if (vsyncListener) {
854 vsyncListener->onVsync(timestamp, 0);
855 }
856 }
857
notifyExpectedPresent(int64_t timestamp,int32_t frameIntervalNs)858 int32_t ExynosPrimaryDisplay::notifyExpectedPresent(int64_t timestamp, int32_t frameIntervalNs) {
859 if (mVariableRefreshRateController) {
860 mVariableRefreshRateController->notifyExpectedPresent(timestamp, frameIntervalNs);
861 }
862 return NO_ERROR;
863 }
864
setPresentTimeoutParameters(int timeoutNs,const std::vector<std::pair<uint32_t,uint32_t>> & settings)865 int32_t ExynosPrimaryDisplay::setPresentTimeoutParameters(
866 int timeoutNs, const std::vector<std::pair<uint32_t, uint32_t>>& settings) {
867 if (mVariableRefreshRateController) {
868 mVariableRefreshRateController->setPresentTimeoutParameters(timeoutNs, settings);
869 return NO_ERROR;
870 }
871 return HWC2_ERROR_UNSUPPORTED;
872 }
873
setPresentTimeoutController(uint32_t controllerType)874 int32_t ExynosPrimaryDisplay::setPresentTimeoutController(uint32_t controllerType) {
875 if (mVariableRefreshRateController) {
876 mVariableRefreshRateController->setPresentTimeoutController(controllerType);
877 return NO_ERROR;
878 }
879 return HWC2_ERROR_UNSUPPORTED;
880 }
881
setRefreshRateChangedCallbackDebugEnabled(bool enabled)882 int32_t ExynosPrimaryDisplay::setRefreshRateChangedCallbackDebugEnabled(bool enabled) {
883 if (mVariableRefreshRateController) {
884 mVariableRefreshRateController->enableRefreshRateCalculator(enabled);
885 } else {
886 ExynosDisplay::setRefreshRateChangedCallbackDebugEnabled(enabled);
887 }
888 return NO_ERROR;
889 }
890
setLhbmDisplayConfigLocked(uint32_t peakRate)891 int32_t ExynosPrimaryDisplay::setLhbmDisplayConfigLocked(uint32_t peakRate) {
892 auto hwConfig = mDisplayInterface->getActiveModeId();
893 auto config = getConfigId(peakRate, mDisplayConfigs[hwConfig].width,
894 mDisplayConfigs[hwConfig].height);
895 if (config == UINT_MAX) {
896 DISPLAY_LOGE("%s: failed to get config for rate=%d", __func__, peakRate);
897 return -EINVAL;
898 }
899
900 if (mPendingConfig == UINT_MAX && mActiveConfig != config) mPendingConfig = mActiveConfig;
901 if (config != hwConfig) {
902 if (ExynosDisplay::setActiveConfigInternal(config, true) == HWC2_ERROR_NONE) {
903 DISPLAY_LOGI("%s: succeeded to set config=%d rate=%d", __func__, config, peakRate);
904 } else {
905 DISPLAY_LOGW("%s: failed to set config=%d rate=%d", __func__, config, peakRate);
906 }
907 } else {
908 DISPLAY_LOGI("%s: keep config=%d rate=%d", __func__, config, peakRate);
909 }
910 enableConfigSetting(false);
911 return OK;
912 }
913
restoreLhbmDisplayConfigLocked()914 void ExynosPrimaryDisplay::restoreLhbmDisplayConfigLocked() {
915 enableConfigSetting(true);
916 hwc2_config_t pendingConfig = mPendingConfig;
917 auto hwConfig = mDisplayInterface->getActiveModeId();
918 if (pendingConfig != UINT_MAX && pendingConfig != hwConfig) {
919 if (applyPendingConfig() == HWC2_ERROR_NONE) {
920 DISPLAY_LOGI("%s: succeeded to set config=%d rate=%d", __func__, pendingConfig,
921 getRefreshRate(pendingConfig));
922 } else {
923 DISPLAY_LOGE("%s: failed to set config=%d rate=%d", __func__, pendingConfig,
924 getRefreshRate(pendingConfig));
925 }
926 } else {
927 mPendingConfig = UINT_MAX;
928 DISPLAY_LOGI("%s: keep config=%d rate=%d", __func__, hwConfig, getRefreshRate(hwConfig));
929 }
930 }
931
932 // This function should be called by other threads (e.g. sensor HAL).
933 // HWCService can call this function but it should be for test purpose only.
setLhbmState(bool enabled)934 int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) {
935 int ret = OK;
936 // NOTE: mLhbmOn could be set to false at any time by setPowerOff in another
937 // thread. Make sure no side effect if that happens. Or add lock if we have
938 // to when new code is added.
939 DISPLAY_ATRACE_CALL();
940 DISPLAY_LOGI("%s: enabled=%d", __func__, enabled);
941 {
942 ATRACE_NAME("wait_for_power_on");
943 std::unique_lock<std::mutex> lock(mPowerModeMutex);
944 if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON)) {
945 mNotifyPowerOn = true;
946 if (!mPowerOnCondition.wait_for(lock, std::chrono::milliseconds(2000), [this]() {
947 return (mPowerModeState.has_value() &&
948 (*mPowerModeState == HWC2_POWER_MODE_ON));
949 })) {
950 DISPLAY_LOGW("%s: wait for power mode on timeout !", __func__);
951 return TIMED_OUT;
952 }
953 }
954 }
955
956 auto lhbmSysfs = mBrightnessController->GetPanelSysfileByIndex(
957 BrightnessController::kLocalHbmModeFileNode);
958 ret = mBrightnessController->checkSysfsStatus(lhbmSysfs,
959 {std::to_string(static_cast<int>(
960 BrightnessController::LhbmMode::DISABLED))},
961 0);
962 bool wasDisabled = ret == OK;
963 if (!enabled && wasDisabled) {
964 DISPLAY_LOGW("%s: lhbm is at DISABLED state, skip disabling", __func__);
965 return NO_ERROR;
966 } else if (enabled && !wasDisabled) {
967 requestLhbm(true);
968 DISPLAY_LOGI("%s: lhbm is at ENABLING or ENABLED state, re-enable to reset timeout timer",
969 __func__);
970 return NO_ERROR;
971 }
972
973 std::vector<std::string> checkingValue;
974 if (!enabled) {
975 ATRACE_NAME("disable_lhbm");
976 requestLhbm(false);
977 {
978 ATRACE_NAME("wait_for_lhbm_off_cmd");
979 checkingValue = {
980 std::to_string(static_cast<int>(BrightnessController::LhbmMode::DISABLED))};
981 ret = mBrightnessController->checkSysfsStatus(lhbmSysfs, checkingValue,
982 ms2ns(kSysfsCheckTimeoutMs));
983 if (ret != OK) {
984 DISPLAY_LOGW("%s: failed to send lhbm-off cmd", __func__);
985 }
986 }
987 {
988 Mutex::Autolock lock(mDisplayMutex);
989 restoreLhbmDisplayConfigLocked();
990 }
991 setLHBMRefreshRateThrottle(0);
992 mLhbmOn = false;
993 return NO_ERROR;
994 }
995
996 ATRACE_NAME("enable_lhbm");
997 int64_t lhbmWaitForRrNanos, lhbmEnablingNanos, lhbmEnablingDoneNanos;
998 bool enablingStateSupported = !mFramesToReachLhbmPeakBrightness;
999 uint32_t peakRate = 0;
1000 auto rrSysfs = mBrightnessController->GetPanelRefreshRateSysfile();
1001 lhbmWaitForRrNanos = systemTime(SYSTEM_TIME_MONOTONIC);
1002 {
1003 Mutex::Autolock lock(mDisplayMutex);
1004 peakRate = getPeakRefreshRate();
1005 if (peakRate < 60) {
1006 DISPLAY_LOGE("%s: invalid peak rate=%d", __func__, peakRate);
1007 return -EINVAL;
1008 }
1009 ret = setLhbmDisplayConfigLocked(peakRate);
1010 if (ret != OK) return ret;
1011 }
1012
1013 if (mBrightnessController->fileExists(rrSysfs)) {
1014 ATRACE_NAME("wait_for_peak_rate_cmd");
1015 ret = mBrightnessController->checkSysfsStatus(rrSysfs, {std::to_string(peakRate)},
1016 ms2ns(kLhbmWaitForPeakRefreshRateMs));
1017 if (ret != OK) {
1018 DISPLAY_LOGW("%s: failed to poll peak refresh rate=%d, ret=%d", __func__, peakRate,
1019 ret);
1020 }
1021 } else {
1022 ATRACE_NAME("wait_for_peak_rate_blindly");
1023 DISPLAY_LOGW("%s: missing refresh rate path: %s", __func__, rrSysfs.c_str());
1024 // blindly wait for (3 full frames + 1 frame uncertainty) to ensure DM finishes
1025 // switching refresh rate
1026 for (int32_t i = 0; i < 4; i++) {
1027 if (mDisplayInterface->waitVBlank()) {
1028 DISPLAY_LOGE("%s: failed to blindly wait for peak refresh rate=%d, i=%d", __func__,
1029 peakRate, i);
1030 ret = -ENODEV;
1031 goto enable_err;
1032 }
1033 }
1034 }
1035
1036 setLHBMRefreshRateThrottle(kLhbmRefreshRateThrottleMs);
1037 checkingValue = {std::to_string(static_cast<int>(BrightnessController::LhbmMode::ENABLING)),
1038 std::to_string(static_cast<int>(BrightnessController::LhbmMode::ENABLED))};
1039 lhbmEnablingNanos = systemTime(SYSTEM_TIME_MONOTONIC);
1040 requestLhbm(true);
1041 {
1042 ATRACE_NAME("wait_for_lhbm_on_cmd");
1043 ret = mBrightnessController->checkSysfsStatus(lhbmSysfs, checkingValue,
1044 ms2ns(kSysfsCheckTimeoutMs));
1045 if (ret != OK) {
1046 DISPLAY_LOGE("%s: failed to enable lhbm", __func__);
1047 setLHBMRefreshRateThrottle(0);
1048 goto enable_err;
1049 }
1050 }
1051
1052 lhbmEnablingDoneNanos = systemTime(SYSTEM_TIME_MONOTONIC);
1053 {
1054 ATRACE_NAME("wait_for_peak_brightness");
1055 if (enablingStateSupported) {
1056 ret = mBrightnessController->checkSysfsStatus(lhbmSysfs,
1057 {std::to_string(static_cast<int>(
1058 BrightnessController::LhbmMode::ENABLED))},
1059 ms2ns(kSysfsCheckTimeoutMs));
1060 if (ret != OK) {
1061 DISPLAY_LOGE("%s: failed to wait for lhbm becoming effective", __func__);
1062 goto enable_err;
1063 }
1064 } else {
1065 // lhbm takes effect at next vblank
1066 for (int32_t i = mFramesToReachLhbmPeakBrightness + 1; i > 0; i--) {
1067 ret = mDisplayInterface->waitVBlank();
1068 if (ret) {
1069 DISPLAY_LOGE("%s: failed to wait vblank for peak brightness, %d", __func__, i);
1070 goto enable_err;
1071 }
1072 }
1073 }
1074 }
1075 DISPLAY_LOGI("%s: latency: %04d = %03d|rr@%03d + %03d|en + %03d|boost@%s", __func__,
1076 getTimestampDeltaMs(0, lhbmWaitForRrNanos),
1077 getTimestampDeltaMs(lhbmEnablingNanos, lhbmWaitForRrNanos), peakRate,
1078 getTimestampDeltaMs(lhbmEnablingDoneNanos, lhbmEnablingNanos),
1079 getTimestampDeltaMs(0, lhbmEnablingDoneNanos),
1080 enablingStateSupported ? "polling" : "fixed");
1081
1082 mLhbmOn = true;
1083 if (!mPowerModeState.has_value() || (*mPowerModeState == HWC2_POWER_MODE_OFF && mLhbmOn)) {
1084 mLhbmOn = false;
1085 DISPLAY_LOGE("%s: power off during request lhbm on", __func__);
1086 return -EINVAL;
1087 }
1088 return NO_ERROR;
1089 enable_err:
1090 {
1091 // We may receive LHBM request during the power off sequence due to the
1092 // race condition between display and sensor. If the failure happens
1093 // after requestLhbm(), we will get a wrong LHBM state in the 1st commit
1094 // after power on. We should reset the state in this case.
1095 std::unique_lock<std::mutex> lock(mPowerModeMutex);
1096 if (!mPowerModeState.has_value() || (*mPowerModeState == HWC2_POWER_MODE_OFF)) {
1097 DISPLAY_LOGW("%s: request lhbm during power off sequence, reset the state", __func__);
1098 mBrightnessController->resetLhbmState();
1099 }
1100 }
1101
1102 Mutex::Autolock lock(mDisplayMutex);
1103 restoreLhbmDisplayConfigLocked();
1104 return ret;
1105 }
1106
getLhbmState()1107 bool ExynosPrimaryDisplay::getLhbmState() {
1108 return mLhbmOn;
1109 }
1110
setLHBMRefreshRateThrottle(const uint32_t delayMs)1111 void ExynosPrimaryDisplay::setLHBMRefreshRateThrottle(const uint32_t delayMs) {
1112 ATRACE_CALL();
1113
1114 if (delayMs) {
1115 // make new throttle take effect
1116 mLastRefreshRateAppliedNanos = systemTime(SYSTEM_TIME_MONOTONIC);
1117 DISPLAY_ATRACE_INT64("LastRefreshRateAppliedMs", ns2ms(mLastRefreshRateAppliedNanos));
1118 }
1119
1120 setRefreshRateThrottleNanos(std::chrono::duration_cast<std::chrono::nanoseconds>(
1121 std::chrono::milliseconds(delayMs))
1122 .count(),
1123 RrThrottleRequester::LHBM);
1124 }
1125
setEarlyWakeupDisplay()1126 void ExynosPrimaryDisplay::setEarlyWakeupDisplay() {
1127 if (mEarlyWakeupDispFd) {
1128 writeFileNode(mEarlyWakeupDispFd, 1);
1129 }
1130 }
1131
setExpectedPresentTime(uint64_t timestamp,int frameIntervalNs)1132 void ExynosPrimaryDisplay::setExpectedPresentTime(uint64_t timestamp, int frameIntervalNs) {
1133 mExpectedPresentTimeAndInterval.store(std::make_tuple(timestamp, frameIntervalNs));
1134 // Forward presentDisplay if there is a listener.
1135 const auto presentListener = getPresentListener();
1136 if (presentListener) {
1137 presentListener->setExpectedPresentTime(timestamp, frameIntervalNs);
1138 }
1139 }
1140
getPendingExpectedPresentTime()1141 uint64_t ExynosPrimaryDisplay::getPendingExpectedPresentTime() {
1142 if (mExpectedPresentTimeAndInterval.is_dirty()) {
1143 return std::get<0>(mExpectedPresentTimeAndInterval.get());
1144 }
1145
1146 return 0;
1147 }
1148
getPendingFrameInterval()1149 int ExynosPrimaryDisplay::getPendingFrameInterval() {
1150 if (mExpectedPresentTimeAndInterval.is_dirty()) {
1151 return std::get<1>(mExpectedPresentTimeAndInterval.get());
1152 }
1153
1154 return 0;
1155 }
1156
applyExpectedPresentTime()1157 void ExynosPrimaryDisplay::applyExpectedPresentTime() {
1158 mExpectedPresentTimeAndInterval.clear_dirty();
1159 }
1160
setDisplayIdleTimer(const int32_t timeoutMs)1161 int32_t ExynosPrimaryDisplay::setDisplayIdleTimer(const int32_t timeoutMs) {
1162 bool support = false;
1163 if (getDisplayIdleTimerSupport(support) || support == false) {
1164 return HWC2_ERROR_UNSUPPORTED;
1165 }
1166
1167 if (timeoutMs < 0) {
1168 return HWC2_ERROR_BAD_PARAMETER;
1169 }
1170
1171 if (timeoutMs > 0) {
1172 setDisplayIdleDelayNanos(std::chrono::duration_cast<std::chrono::nanoseconds>(
1173 std::chrono::milliseconds(timeoutMs))
1174 .count(),
1175 DispIdleTimerRequester::SF);
1176 }
1177
1178 bool enabled = (timeoutMs > 0);
1179 if (enabled != mDisplayIdleTimerEnabled) {
1180 if (setDisplayIdleTimerEnabled(enabled) == NO_ERROR) {
1181 mDisplayIdleTimerEnabled = enabled;
1182 }
1183 }
1184
1185 return HWC2_ERROR_NONE;
1186 }
1187
getDisplayIdleTimerEnabled(bool & enabled)1188 int32_t ExynosPrimaryDisplay::getDisplayIdleTimerEnabled(bool &enabled) {
1189 bool support = false;
1190 if (getDisplayIdleTimerSupport(support) || support == false) {
1191 return HWC2_ERROR_UNSUPPORTED;
1192 }
1193
1194 const std::string path = getPanelSysfsPath() + "panel_idle";
1195 std::ifstream ifs(path);
1196 if (!ifs.is_open()) {
1197 ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
1198 return errno;
1199 } else {
1200 std::string panel_idle;
1201 std::getline(ifs, panel_idle);
1202 ifs.close();
1203 enabled = (panel_idle == "1");
1204 ALOGI("%s() get panel_idle(%d) from the sysfs node", __func__, enabled);
1205 }
1206 return NO_ERROR;
1207 }
1208
setDisplayIdleTimerEnabled(const bool enabled)1209 int32_t ExynosPrimaryDisplay::setDisplayIdleTimerEnabled(const bool enabled) {
1210 const std::string path = getPanelSysfsPath() + "panel_idle";
1211 std::ofstream ofs(path);
1212 if (!ofs.is_open()) {
1213 ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
1214 return errno;
1215 } else {
1216 ofs << enabled;
1217 ofs.close();
1218 ALOGI("%s() writes panel_idle(%d) to the sysfs node", __func__, enabled);
1219 }
1220 return NO_ERROR;
1221 }
1222
setDisplayIdleDelayNanos(const int32_t delayNanos,const DispIdleTimerRequester requester)1223 int32_t ExynosPrimaryDisplay::setDisplayIdleDelayNanos(const int32_t delayNanos,
1224 const DispIdleTimerRequester requester) {
1225 std::lock_guard<std::mutex> lock(mDisplayIdleDelayMutex);
1226
1227 int64_t maxDelayNanos = 0;
1228 mDisplayIdleTimerNanos[toUnderlying(requester)] = delayNanos;
1229 for (uint32_t i = 0; i < toUnderlying(DispIdleTimerRequester::MAX); i++) {
1230 if (mDisplayIdleTimerNanos[i] > maxDelayNanos) {
1231 maxDelayNanos = mDisplayIdleTimerNanos[i];
1232 }
1233 }
1234
1235 if (mDisplayIdleDelayNanos == maxDelayNanos) {
1236 return NO_ERROR;
1237 }
1238
1239 mDisplayIdleDelayNanos = maxDelayNanos;
1240
1241 const int32_t displayIdleDelayMs = std::chrono::duration_cast<std::chrono::milliseconds>(
1242 std::chrono::nanoseconds(mDisplayIdleDelayNanos))
1243 .count();
1244 const std::string path = getPanelSysfsPath() + "idle_delay_ms";
1245 std::ofstream ofs(path);
1246 if (!ofs.is_open()) {
1247 ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
1248 return errno;
1249 } else {
1250 ofs << displayIdleDelayMs;
1251 ALOGI("%s() writes idle_delay_ms(%d) to the sysfs node (0x%x)", __func__,
1252 displayIdleDelayMs, ofs.rdstate());
1253 ofs.close();
1254 }
1255 return NO_ERROR;
1256 }
1257
initDisplayHandleIdleExit()1258 void ExynosPrimaryDisplay::initDisplayHandleIdleExit() {
1259 if (bool support; getDisplayIdleTimerSupport(support) || support == false) {
1260 return;
1261 }
1262
1263 const std::string path = getPanelSysfsPath() + "panel_need_handle_idle_exit";
1264 mDisplayNeedHandleIdleExitOfs.open(path, std::ofstream::out);
1265 if (!mDisplayNeedHandleIdleExitOfs.is_open()) {
1266 ALOGI("%s() '%s' doesn't exist(%s)", __func__, path.c_str(), strerror(errno));
1267 }
1268
1269 setDisplayNeedHandleIdleExit(false, true);
1270 }
1271
setDisplayNeedHandleIdleExit(const bool needed,const bool force)1272 void ExynosPrimaryDisplay::setDisplayNeedHandleIdleExit(const bool needed, const bool force) {
1273 if (!mDisplayNeedHandleIdleExitOfs.is_open()) {
1274 return;
1275 }
1276
1277 if (needed == mDisplayNeedHandleIdleExit && !force) {
1278 return;
1279 }
1280
1281 mDisplayNeedHandleIdleExitOfs << needed;
1282 if (mDisplayNeedHandleIdleExitOfs.fail()) {
1283 ALOGW("%s() failed to write panel_need_handle_idle_exit(%d) to sysfs node %s", __func__,
1284 needed, strerror(errno));
1285 return;
1286 }
1287
1288 mDisplayNeedHandleIdleExitOfs.flush();
1289 if (mDisplayNeedHandleIdleExitOfs.fail()) {
1290 ALOGW("%s() failed to flush panel_need_handle_idle_exit(%d) to sysfs node %s", __func__,
1291 needed, strerror(errno));
1292 return;
1293 }
1294
1295 ALOGI("%s() writes panel_need_handle_idle_exit(%d) to sysfs node", __func__, needed);
1296 mDisplayNeedHandleIdleExit = needed;
1297 }
1298
handleDisplayIdleEnter(const uint32_t idleTeRefreshRate)1299 void ExynosPrimaryDisplay::handleDisplayIdleEnter(const uint32_t idleTeRefreshRate) {
1300 bool needed = false;
1301 {
1302 Mutex::Autolock lock1(mDisplayMutex);
1303 uint32_t btsRefreshRate = getBtsRefreshRate();
1304 if (idleTeRefreshRate <= btsRefreshRate) {
1305 return;
1306 }
1307 Mutex::Autolock lock2(mDRMutex);
1308 for (size_t i = 0; i < mLayers.size(); i++) {
1309 if (mLayers[i]->mOtfMPP && mLayers[i]->mM2mMPP == nullptr &&
1310 !mLayers[i]->checkBtsCap(idleTeRefreshRate)) {
1311 needed = true;
1312 break;
1313 }
1314 }
1315 }
1316
1317 setDisplayNeedHandleIdleExit(needed, false);
1318 }
1319
setFixedTe2Rate(const int targetTe2RateHz)1320 int32_t ExynosPrimaryDisplay::setFixedTe2Rate(const int targetTe2RateHz) {
1321 if (mDisplayTe2Manager) {
1322 return mDisplayTe2Manager->setFixedTe2Rate(targetTe2RateHz);
1323 } else {
1324 return HWC2_ERROR_UNSUPPORTED;
1325 }
1326 }
1327
setMinIdleRefreshRate(const int targetFps,const RrThrottleRequester requester)1328 int32_t ExynosPrimaryDisplay::setMinIdleRefreshRate(const int targetFps,
1329 const RrThrottleRequester requester) {
1330 if (targetFps < 0) {
1331 return HWC2_ERROR_BAD_PARAMETER;
1332 }
1333 int fps = targetFps;
1334 if ((requester == RrThrottleRequester::BRIGHTNESS) &&
1335 (!mBrightnessBlockingZonesLookupTable.empty())) {
1336 std::unique_lock<std::mutex> lock(mPowerModeMutex);
1337 // Only check the BRIGHTNESS vote when the power is on.
1338 if (mPowerModeState.has_value() && (*mPowerModeState == HWC2_POWER_MODE_ON)) {
1339 auto res = mBrightnessController->getBrightnessNitsAndMode();
1340 if (res != std::nullopt) {
1341 const auto it =
1342 mBrightnessBlockingZonesLookupTable.upper_bound(std::get<0>(res.value()));
1343 ALOGD("%s requester = BRIGHTNESS, brightness = %f nits, vote minimum refresh rate "
1344 "to %d",
1345 __func__, std::get<0>(res.value()), it->second);
1346 fps = std::max(fps, it->second);
1347 if (mDisplayConfigs.count(mActiveConfig)) {
1348 if (fps > mDisplayConfigs[mActiveConfig].refreshRate) {
1349 ALOGI("%s() The brightness blocking zone votes for the FPS = %d, which is "
1350 "higher than the maximum refresh rate of the current configuration = "
1351 "%d",
1352 __func__, fps, mDisplayConfigs[mActiveConfig].refreshRate);
1353 fps = mDisplayConfigs[mActiveConfig].refreshRate;
1354 }
1355 }
1356 }
1357 }
1358 }
1359
1360 std::lock_guard<std::mutex> lock(mMinIdleRefreshRateMutex);
1361 if (fps == mRrThrottleFps[toUnderlying(requester)]) return NO_ERROR;
1362
1363 ALOGD("%s requester %u, fps %d", __func__, toUnderlying(requester), fps);
1364 mRrThrottleFps[toUnderlying(requester)] = fps;
1365 int maxMinIdleFps = 0;
1366 for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
1367 if (mRrThrottleFps[i] > maxMinIdleFps) {
1368 maxMinIdleFps = mRrThrottleFps[i];
1369 }
1370 }
1371
1372 {
1373 std::lock_guard<std::mutex> lock(mPowerModeMutex);
1374 bool dozeMode = (mPowerModeState.has_value() &&
1375 (*mPowerModeState == HWC2_POWER_MODE_DOZE ||
1376 *mPowerModeState == HWC2_POWER_MODE_DOZE_SUSPEND));
1377 // Currently only proximity sensor will request the min refresh rate via this API with
1378 // PIXEL_DISP (or TEST for the debugging command). It will request a non-zero value,
1379 // e.g. 30Hz, if it's active, and request zero if it's inactive. So we can know its state
1380 // and update the TE2 option accordingly.
1381 if (mDisplayTe2Manager &&
1382 (requester == RrThrottleRequester::PIXEL_DISP ||
1383 requester == RrThrottleRequester::TEST)) {
1384 bool proximityActive = !!targetFps;
1385 ALOGD("%s: proximity state %s, min %dhz, doze mode %d", __func__,
1386 proximityActive ? "active" : "inactive", targetFps, dozeMode);
1387 mDisplayTe2Manager->updateTe2OptionForProximity(proximityActive, targetFps, dozeMode);
1388 }
1389
1390 if (maxMinIdleFps == mMinIdleRefreshRate) return NO_ERROR;
1391
1392 if (mVariableRefreshRateController) {
1393 if (dozeMode && maxMinIdleFps != kMinIdleRefreshRateForDozeMode) {
1394 ALOGW("%s: setting %dhz in doze mode (expect %dhz)", __func__, maxMinIdleFps,
1395 kMinIdleRefreshRateForDozeMode);
1396 mMinIdleRefreshRate = maxMinIdleFps;
1397 return NO_ERROR;
1398 }
1399
1400 int ret = mVariableRefreshRateController
1401 ->setFixedRefreshRateRange(maxMinIdleFps, mRefreshRateDelayNanos);
1402 if (ret >= 0) {
1403 mMinIdleRefreshRate = maxMinIdleFps;
1404 return NO_ERROR;
1405 }
1406 return ret;
1407 }
1408 }
1409
1410 const std::string path = getPanelSysfsPath() + "min_vrefresh";
1411 std::ofstream ofs(path);
1412 if (!ofs.is_open()) {
1413 ALOGW("%s Unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
1414 return errno;
1415 } else {
1416 ofs << maxMinIdleFps;
1417 ofs.close();
1418 ALOGI("ExynosPrimaryDisplay::%s() writes min_vrefresh(%d) to the sysfs node", __func__,
1419 maxMinIdleFps);
1420 }
1421 mMinIdleRefreshRate = maxMinIdleFps;
1422 return NO_ERROR;
1423 }
1424
setRefreshRateThrottleNanos(const int64_t delayNanos,const RrThrottleRequester requester)1425 int32_t ExynosPrimaryDisplay::setRefreshRateThrottleNanos(const int64_t delayNanos,
1426 const RrThrottleRequester requester) {
1427 ATRACE_CALL();
1428 if (delayNanos < 0) {
1429 ALOGW("%s() set invalid delay(%" PRId64 ")", __func__, delayNanos);
1430 return BAD_VALUE;
1431 }
1432
1433 int32_t ret = NO_ERROR;
1434 int64_t maxDelayNanos = 0;
1435 {
1436 std::lock_guard<std::mutex> lock(mIdleRefreshRateThrottleMutex);
1437 if (delayNanos == mRrThrottleNanos[toUnderlying(requester)]) return NO_ERROR;
1438
1439 ALOGI("%s() requester(%u) set delay to %" PRId64 "ns", __func__, toUnderlying(requester),
1440 delayNanos);
1441 mRrThrottleNanos[toUnderlying(requester)] = delayNanos;
1442 uint32_t maxDelayRequester = toUnderlying(RrThrottleRequester::MAX);
1443 for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
1444 if (mRrThrottleNanos[i] > maxDelayNanos) {
1445 maxDelayRequester = i;
1446 maxDelayNanos = mRrThrottleNanos[i];
1447 }
1448 }
1449
1450 DISPLAY_ATRACE_INT("RefreshRateDelayRequester", maxDelayRequester);
1451 DISPLAY_ATRACE_INT64("RefreshRateDelay", ns2ms(maxDelayNanos));
1452 if (mRefreshRateDelayNanos == maxDelayNanos) {
1453 return NO_ERROR;
1454 }
1455
1456 if (mVariableRefreshRateController) {
1457 int ret = mVariableRefreshRateController->setFixedRefreshRateRange(mMinIdleRefreshRate,
1458 maxDelayNanos);
1459 if (ret >= 0) {
1460 mRefreshRateDelayNanos = maxDelayNanos;
1461 return NO_ERROR;
1462 }
1463 return ret;
1464 }
1465
1466 ret = setDisplayIdleDelayNanos(maxDelayNanos, DispIdleTimerRequester::RR_THROTTLE);
1467 if (ret == NO_ERROR) {
1468 mRefreshRateDelayNanos = maxDelayNanos;
1469 }
1470 }
1471
1472 Mutex::Autolock lock(mDisplayMutex);
1473 if (ret == NO_ERROR) {
1474 recalculateTimelineLocked(maxDelayNanos);
1475 }
1476
1477 return ret;
1478 }
1479
dump(String8 & result)1480 void ExynosPrimaryDisplay::dump(String8 &result) {
1481 ExynosDisplay::dump(result);
1482 result.appendFormat("Display idle timer: %s\n",
1483 (mDisplayIdleTimerEnabled) ? "enabled" : "disabled");
1484 for (uint32_t i = 0; i < toUnderlying(DispIdleTimerRequester::MAX); i++) {
1485 result.appendFormat("\t[%u] vote to %" PRId64 " ns\n", i, mDisplayIdleTimerNanos[i]);
1486 }
1487
1488 if (!mBrightnessBlockingZonesLookupTable.empty()) {
1489 int upperBound;
1490 int lowerBound = INT_MIN;
1491 result.appendFormat("Brightness blocking zone lookup table:\n");
1492 for (const auto& brightnessBlockingZone : mBrightnessBlockingZonesLookupTable) {
1493 upperBound = brightnessBlockingZone.first;
1494 result.appendFormat("\tBrightness blocking zone: range [%s %s) fps = %d\n",
1495 (lowerBound == INT_MIN ? "Min"
1496 : std::to_string(lowerBound).c_str()),
1497 (upperBound == INT_MAX ? "Max"
1498 : std::to_string(upperBound).c_str()),
1499 brightnessBlockingZone.second);
1500 lowerBound = upperBound;
1501 }
1502 } else {
1503 result.appendFormat("\n");
1504 }
1505
1506 result.appendFormat("Min idle refresh rate: %d\n", mMinIdleRefreshRate);
1507 for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
1508 result.appendFormat("\t[%u] vote to %d hz\n", i, mRrThrottleFps[i]);
1509 }
1510
1511 result.appendFormat("Refresh rate delay: %" PRId64 " ns\n", mRefreshRateDelayNanos);
1512 for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
1513 result.appendFormat("\t[%u] vote to %" PRId64 " ns\n", i, mRrThrottleNanos[i]);
1514 }
1515 result.appendFormat("\n");
1516 }
1517
calculateTimelineLocked(hwc2_config_t config,hwc_vsync_period_change_constraints_t * vsyncPeriodChangeConstraints,hwc_vsync_period_change_timeline_t * outTimeline)1518 void ExynosPrimaryDisplay::calculateTimelineLocked(
1519 hwc2_config_t config, hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
1520 hwc_vsync_period_change_timeline_t* outTimeline) {
1521 ATRACE_CALL();
1522 int64_t desiredUpdateTimeNanos = vsyncPeriodChangeConstraints->desiredTimeNanos;
1523 const int64_t origDesiredUpdateTimeNanos = desiredUpdateTimeNanos;
1524 int64_t threshold = 0;
1525 int64_t lastUpdateDelta = 0;
1526 int64_t actualChangeTime = 0;
1527 bool isDelayed = false;
1528
1529 /* actualChangeTime includes transient duration */
1530 mDisplayInterface->getVsyncAppliedTime(config, &actualChangeTime);
1531
1532 outTimeline->refreshRequired = true;
1533
1534 /* When the refresh rate changes from high to low, check if RR throttle is needed */
1535 {
1536 std::lock_guard<std::mutex> lock(mIdleRefreshRateThrottleMutex);
1537 threshold = mRefreshRateDelayNanos;
1538 mRrUseDelayNanos = 0;
1539 mIsRrNeedCheckDelay =
1540 mDisplayConfigs[mActiveConfig].vsyncPeriod < mDisplayConfigs[config].vsyncPeriod;
1541 if (threshold != 0 && mLastRefreshRateAppliedNanos != 0 && mIsRrNeedCheckDelay) {
1542 lastUpdateDelta = desiredUpdateTimeNanos - mLastRefreshRateAppliedNanos;
1543 if (lastUpdateDelta < threshold) {
1544 /* in this case, the active config change needs to be delayed */
1545 isDelayed = true;
1546 desiredUpdateTimeNanos += threshold - lastUpdateDelta;
1547 mRrUseDelayNanos = threshold;
1548 }
1549 }
1550 }
1551
1552 mVsyncPeriodChangeConstraints.desiredTimeNanos = desiredUpdateTimeNanos;
1553
1554 getConfigAppliedTime(mVsyncPeriodChangeConstraints.desiredTimeNanos, actualChangeTime,
1555 outTimeline->newVsyncAppliedTimeNanos, outTimeline->refreshTimeNanos);
1556
1557 const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
1558 DISPLAY_LOGD_AND_ATRACE_NAME(eDebugDisplayConfig,
1559 "requested config : %d(%d)->%d(%d), isDelay:%d,"
1560 " delta %" PRId64 ", delay %" PRId64 ", threshold %" PRId64 ", "
1561 "now:%" PRId64 ", desired %" PRId64 "->%" PRId64
1562 ", newVsyncAppliedTimeNanos : %" PRId64
1563 ", refreshTimeNanos:%" PRId64
1564 ", mLastRefreshRateAppliedNanos:%" PRId64,
1565 mActiveConfig, mDisplayConfigs[mActiveConfig].vsyncPeriod, config,
1566 mDisplayConfigs[config].vsyncPeriod, isDelayed,
1567 ns2ms(lastUpdateDelta), ns2ms(threshold - lastUpdateDelta),
1568 ns2ms(threshold), ns2ms(now), ns2ms(origDesiredUpdateTimeNanos),
1569 ns2ms(mVsyncPeriodChangeConstraints.desiredTimeNanos),
1570 ns2ms(outTimeline->newVsyncAppliedTimeNanos),
1571 ns2ms(outTimeline->refreshTimeNanos),
1572 ns2ms(mLastRefreshRateAppliedNanos));
1573
1574 DISPLAY_ATRACE_INT64("TimeToApplyConfig",
1575 ns2ms(mVsyncPeriodChangeConstraints.desiredTimeNanos - now));
1576 }
1577
recalculateTimelineLocked(int64_t refreshRateDelayNanos)1578 void ExynosPrimaryDisplay::recalculateTimelineLocked(int64_t refreshRateDelayNanos) {
1579 ATRACE_CALL();
1580
1581 if (mConfigRequestState != hwc_request_state_t::SET_CONFIG_STATE_PENDING) {
1582 return;
1583 }
1584
1585 std::lock_guard<std::mutex> lock(mIdleRefreshRateThrottleMutex);
1586 if (!mIsRrNeedCheckDelay) {
1587 return;
1588 }
1589
1590 int64_t desiredUpdateTimeNanos = mVsyncPeriodChangeConstraints.desiredTimeNanos;
1591 if (mRrUseDelayNanos) {
1592 desiredUpdateTimeNanos += (refreshRateDelayNanos - mRrUseDelayNanos);
1593 } else {
1594 int64_t lastUpdateDelta =
1595 mVsyncPeriodChangeConstraints.desiredTimeNanos - mLastRefreshRateAppliedNanos;
1596 if (lastUpdateDelta < refreshRateDelayNanos) {
1597 desiredUpdateTimeNanos += (refreshRateDelayNanos - lastUpdateDelta);
1598 }
1599 }
1600 mRrUseDelayNanos = refreshRateDelayNanos;
1601
1602 const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
1603 if (desiredUpdateTimeNanos > now) {
1604 mVsyncPeriodChangeConstraints.desiredTimeNanos = desiredUpdateTimeNanos;
1605 } else {
1606 mVsyncPeriodChangeConstraints.desiredTimeNanos = now;
1607 }
1608
1609 DISPLAY_ATRACE_INT64("TimeToApplyConfig",
1610 ns2ms(mVsyncPeriodChangeConstraints.desiredTimeNanos - now));
1611 }
1612
updateAppliedActiveConfig(const hwc2_config_t newConfig,const int64_t ts)1613 void ExynosPrimaryDisplay::updateAppliedActiveConfig(const hwc2_config_t newConfig,
1614 const int64_t ts) {
1615 ATRACE_CALL();
1616 if (mAppliedActiveConfig == 0 ||
1617 getDisplayVsyncPeriodFromConfig(mAppliedActiveConfig) !=
1618 getDisplayVsyncPeriodFromConfig(newConfig)) {
1619 DISPLAY_LOGD(eDebugDisplayConfig,
1620 "%s mAppliedActiveConfig(%d->%d), mLastRefreshRateAppliedNanos(%" PRIu64
1621 " -> %" PRIu64 ")",
1622 __func__, mAppliedActiveConfig, newConfig, mLastRefreshRateAppliedNanos, ts);
1623 mLastRefreshRateAppliedNanos = ts;
1624 DISPLAY_ATRACE_INT64("LastRefreshRateAppliedMs", ns2ms(mLastRefreshRateAppliedNanos));
1625 }
1626
1627 mAppliedActiveConfig = newConfig;
1628 }
1629
checkBtsReassignResource(const int32_t vsyncPeriod,const int32_t btsVsyncPeriod)1630 void ExynosPrimaryDisplay::checkBtsReassignResource(const int32_t vsyncPeriod,
1631 const int32_t btsVsyncPeriod) {
1632 ATRACE_CALL();
1633 uint32_t refreshRate = static_cast<uint32_t>(round(nsecsPerSec / vsyncPeriod * 0.1f) * 10);
1634
1635 Mutex::Autolock lock(mDRMutex);
1636 if (vsyncPeriod < btsVsyncPeriod) {
1637 for (size_t i = 0; i < mLayers.size(); i++) {
1638 if (mLayers[i]->mOtfMPP && mLayers[i]->mM2mMPP == nullptr &&
1639 !mLayers[i]->checkBtsCap(refreshRate)) {
1640 mLayers[i]->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
1641 break;
1642 }
1643 }
1644 } else if (vsyncPeriod > btsVsyncPeriod) {
1645 for (size_t i = 0; i < mLayers.size(); i++) {
1646 if (mLayers[i]->mOtfMPP && mLayers[i]->mM2mMPP) {
1647 float srcWidth = mLayers[i]->mSourceCrop.right - mLayers[i]->mSourceCrop.left;
1648 float srcHeight = mLayers[i]->mSourceCrop.bottom - mLayers[i]->mSourceCrop.top;
1649 float resolution = srcWidth * srcHeight * refreshRate / 1000;
1650 float ratioVertical = static_cast<float>(mLayers[i]->mDisplayFrame.bottom -
1651 mLayers[i]->mDisplayFrame.top) /
1652 mYres;
1653
1654 if (mLayers[i]->mOtfMPP->checkDownscaleCap(resolution, ratioVertical)) {
1655 mLayers[i]->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
1656 break;
1657 }
1658 }
1659 }
1660 }
1661 }
1662
isDbmSupported()1663 bool ExynosPrimaryDisplay::isDbmSupported() {
1664 return mBrightnessController->isDbmSupported();
1665 }
1666
setDbmState(bool enabled)1667 int32_t ExynosPrimaryDisplay::setDbmState(bool enabled) {
1668 mBrightnessController->processDimBrightness(enabled);
1669 return NO_ERROR;
1670 }
1671
getPresentListener()1672 PresentListener* ExynosPrimaryDisplay::getPresentListener() {
1673 if (mVariableRefreshRateController) {
1674 return mVariableRefreshRateController.get();
1675 }
1676 return nullptr;
1677 }
1678
getVsyncListener()1679 VsyncListener* ExynosPrimaryDisplay::getVsyncListener() {
1680 if (mVariableRefreshRateController) {
1681 return mVariableRefreshRateController.get();
1682 }
1683 return nullptr;
1684 }
1685
onConfigChange(int configId)1686 void ExynosPrimaryDisplay::onConfigChange(int configId) {
1687 if (mVariableRefreshRateController) {
1688 return mVariableRefreshRateController->setActiveVrrConfiguration(configId);
1689 }
1690 }
1691
getPanelName()1692 const std::string& ExynosPrimaryDisplay::getPanelName() {
1693 if (!mPanelName.empty()) {
1694 return mPanelName;
1695 }
1696
1697 const std::string& sysfs = getPanelSysfsPath();
1698 if (!sysfs.empty()) {
1699 std::string sysfs_rel("panel_name");
1700 if (readLineFromFile(sysfs + "/" + sysfs_rel, mPanelName, '\n') != OK) {
1701 ALOGE("failed reading %s/%s", sysfs.c_str(), sysfs_rel.c_str());
1702 }
1703 }
1704 return mPanelName;
1705 }
1706
registerRefreshRateChangeListener(std::shared_ptr<RefreshRateChangeListener> listener)1707 int32_t ExynosPrimaryDisplay::registerRefreshRateChangeListener(
1708 std::shared_ptr<RefreshRateChangeListener> listener) {
1709 if (!mXrrSettings.versionInfo.hasVrrController()) return HWC2_ERROR_UNSUPPORTED;
1710
1711 if (mVariableRefreshRateController) {
1712 mVariableRefreshRateController->registerRefreshRateChangeListener(listener);
1713 return NO_ERROR;
1714 } else {
1715 return -EINVAL;
1716 }
1717 }
1718