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