1 /*
2 * Copyright (C) 2024 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
17 #include "DisplayTe2Manager.h"
18
DisplayTe2Manager(ExynosDisplay * display,int32_t panelIndex,int fixedTe2DefaultRateHz)19 DisplayTe2Manager::DisplayTe2Manager(ExynosDisplay* display, int32_t panelIndex,
20 int fixedTe2DefaultRateHz)
21 : mDisplay(display),
22 mPanelIndex(panelIndex),
23 mMinRefreshRateForFixedTe2(0),
24 mFixedTe2RateHz(fixedTe2DefaultRateHz),
25 mIsOptionFixedTe2(true),
26 mRefreshRateChangeListenerRegistered(false),
27 mPendingOptionChangeableTe2(false),
28 mPendingFixedTe2Rate(0) {}
29
setTe2Option(bool fixedTe2)30 void DisplayTe2Manager::setTe2Option(bool fixedTe2) {
31 int32_t ret = writeIntToFile(getPanelTe2OptionPath(), fixedTe2);
32 if (!ret) {
33 ALOGI("DisplayTe2Manager::%s writes te2_option(%d) to the sysfs node", __func__, fixedTe2);
34 mIsOptionFixedTe2 = fixedTe2;
35 if (fixedTe2) {
36 setFixedTe2RateInternal(mFixedTe2RateHz, true);
37 } else if (!mRefreshRateChangeListenerRegistered) {
38 // register listener for changeable TE2
39 if (!mDisplay) {
40 ALOGW("DisplayTe2Manager::%s unable to register refresh rate change listener",
41 __func__);
42 } else if (!mDisplay->registerRefreshRateChangeListener(
43 static_cast<std::shared_ptr<RefreshRateChangeListener>>(this))) {
44 mRefreshRateChangeListenerRegistered = true;
45 } else {
46 ALOGW("DisplayTe2Manager::%s failed to register refresh rate change listener",
47 __func__);
48 }
49 }
50 } else {
51 ALOGW("DisplayTe2Manager::%s failed to write te2_option(%d) to the sysfs node", __func__,
52 fixedTe2);
53 }
54 }
55
setTe2Rate(int targetTe2RateHz)56 int32_t DisplayTe2Manager::setTe2Rate(int targetTe2RateHz) {
57 int32_t ret = writeIntToFile(getPanelTe2RatePath(), targetTe2RateHz);
58 if (!ret) {
59 ALOGI("DisplayTe2Manager::%s writes te2_rate_hz(%d) to the sysfs node", __func__,
60 targetTe2RateHz);
61 } else {
62 ALOGW("DisplayTe2Manager::%s failed to write te2_rate_hz(%d) to the sysfs node", __func__,
63 targetTe2RateHz);
64 }
65 return ret;
66 }
67
setFixedTe2Rate(int targetTe2RateHz)68 int32_t DisplayTe2Manager::setFixedTe2Rate(int targetTe2RateHz) {
69 Mutex::Autolock lock(mTe2Mutex);
70 return setFixedTe2RateInternal(targetTe2RateHz, false);
71 }
72
setFixedTe2RateInternal(int targetTe2RateHz,bool enforce)73 int32_t DisplayTe2Manager::setFixedTe2RateInternal(int targetTe2RateHz, bool enforce) {
74 if (!mIsOptionFixedTe2) {
75 ALOGW("DisplayTe2Manager::%s current option is not fixed TE2", __func__);
76 return -EINVAL;
77 }
78 if (targetTe2RateHz == mFixedTe2RateHz && !enforce) {
79 return NO_ERROR;
80 } else {
81 int32_t ret = setTe2Rate(targetTe2RateHz);
82 if (!ret) mFixedTe2RateHz = targetTe2RateHz;
83 return ret;
84 }
85 }
86
setChangeableTe2Rate(int targetTe2RateHz)87 int32_t DisplayTe2Manager::setChangeableTe2Rate(int targetTe2RateHz) {
88 if (mIsOptionFixedTe2) {
89 ALOGW("DisplayTe2Manager::%s current option is not changeable", __func__);
90 return -EINVAL;
91 }
92 if (!mDisplay) {
93 ALOGW("DisplayTe2Manager::%s unable to get peak refresh rate", __func__);
94 return -EINVAL;
95 }
96
97 // While the proximity sensor is active, changeable TE2 should be used. In this case, it
98 // should have the tolerance to receive only min (idle) and target (active) notifications of
99 // refresh rate changes and ignore the intermediate values.
100 if (targetTe2RateHz == mMinRefreshRateForFixedTe2 ||
101 targetTe2RateHz == mDisplay->getRefreshRate(mDisplay->mActiveConfig)) {
102 return setTe2Rate(targetTe2RateHz);
103 } else {
104 return NO_ERROR;
105 }
106 }
107
updateTe2OptionForProximity(bool proximityActive,int minRefreshRate,bool dozeMode)108 void DisplayTe2Manager::updateTe2OptionForProximity(bool proximityActive, int minRefreshRate,
109 bool dozeMode) {
110 Mutex::Autolock lock(mTe2Mutex);
111 bool isOptionFixed = (!proximityActive || (proximityActive && dozeMode));
112 // update the min refresh rate for changeable TE2 usage
113 if (minRefreshRate) mMinRefreshRateForFixedTe2 = minRefreshRate;
114 if (proximityActive && dozeMode) mPendingOptionChangeableTe2 = true;
115 if (isOptionFixed == mIsOptionFixedTe2) return;
116
117 setTe2Option(isOptionFixed);
118 }
119
updateTe2ForDozeMode()120 void DisplayTe2Manager::updateTe2ForDozeMode() {
121 Mutex::Autolock lock(mTe2Mutex);
122 mPendingFixedTe2Rate = mFixedTe2RateHz;
123 mFixedTe2RateHz = kFixedTe2RateForDozeMode;
124
125 if (!mIsOptionFixedTe2) {
126 mPendingOptionChangeableTe2 = true;
127 setTe2Option(true);
128 }
129 }
130
restoreTe2FromDozeMode()131 void DisplayTe2Manager::restoreTe2FromDozeMode() {
132 Mutex::Autolock lock(mTe2Mutex);
133 if (mPendingFixedTe2Rate) mFixedTe2RateHz = mPendingFixedTe2Rate;
134
135 if (mPendingOptionChangeableTe2) {
136 setTe2Option(false);
137 mPendingOptionChangeableTe2 = false;
138 }
139 }
140
onRefreshRateChange(int refreshRate)141 void DisplayTe2Manager::onRefreshRateChange(int refreshRate) {
142 Mutex::Autolock lock(mTe2Mutex);
143 if (!mIsOptionFixedTe2 && refreshRate) setChangeableTe2Rate(refreshRate);
144 }
145
dump(String8 & result) const146 void DisplayTe2Manager::dump(String8& result) const {
147 result.appendFormat("DisplayTe2Manager:\n");
148 result.appendFormat("\tmin refresh rate for fixed TE2: %d\n", mMinRefreshRateForFixedTe2);
149 if (!mIsOptionFixedTe2) {
150 result.appendFormat("\tcurrent TE2: changeable\n");
151 } else {
152 result.appendFormat("\tcurrent TE2: fixed %d Hz\n", mFixedTe2RateHz);
153 }
154 result.appendFormat("\n");
155 }
156