1 /*
2 * Copyright (C) 2022 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 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
18
19 #include "ExynosPrimaryDisplayModule.h"
20
21 #include <cutils/properties.h>
22
23 #include "ExynosHWCHelper.h"
24
25 #define OP_MANAGER_LOGD(msg, ...) \
26 ALOGD("[%s] OperationRateManager::%s:" msg, mDisplay->mDisplayName.c_str(), __func__, \
27 ##__VA_ARGS__)
28 #define OP_MANAGER_LOGI(msg, ...) \
29 ALOGI("[%s] OperationRateManager::%s:" msg, mDisplay->mDisplayName.c_str(), __func__, \
30 ##__VA_ARGS__)
31 #define OP_MANAGER_LOGE(msg, ...) \
32 ALOGE("[%s] OperationRateManager::%s:" msg, mDisplay->mDisplayName.c_str(), __func__, \
33 ##__VA_ARGS__)
34
35 using namespace zuma;
36
ExynosPrimaryDisplayModule(uint32_t index,ExynosDevice * device,const std::string & displayName)37 ExynosPrimaryDisplayModule::ExynosPrimaryDisplayModule(uint32_t index, ExynosDevice* device,
38 const std::string& displayName)
39 : gs201::ExynosPrimaryDisplayModule(index, device, displayName) {
40 int32_t hs_hz = property_get_int32("vendor.primarydisplay.op.hs_hz", 0);
41 int32_t ns_hz = property_get_int32("vendor.primarydisplay.op.ns_hz", 0);
42
43 if (hs_hz && ns_hz) {
44 mOperationRateManager = std::make_unique<OperationRateManager>(this, hs_hz, ns_hz);
45 }
46 }
47
~ExynosPrimaryDisplayModule()48 ExynosPrimaryDisplayModule::~ExynosPrimaryDisplayModule ()
49 {
50
51 }
52
validateWinConfigData()53 int32_t ExynosPrimaryDisplayModule::validateWinConfigData()
54 {
55 return ExynosDisplay::validateWinConfigData();
56 }
57
getTargetOperationRate() const58 int32_t ExynosPrimaryDisplayModule::OperationRateManager::getTargetOperationRate() const {
59 if (mDisplayPowerMode == HWC2_POWER_MODE_DOZE ||
60 mDisplayPowerMode == HWC2_POWER_MODE_DOZE_SUSPEND) {
61 return LP_OP_RATE;
62 } else {
63 return mDisplayTargetOperationRate;
64 }
65 }
66
setTargetOperationRate(const int32_t rate)67 int32_t ExynosPrimaryDisplayModule::OperationRateManager::setTargetOperationRate(
68 const int32_t rate) {
69 if (mDisplayTargetOperationRate == rate) return NO_ERROR;
70
71 OP_MANAGER_LOGI("set target operation rate %d", rate);
72 mDisplayTargetOperationRate = rate;
73
74 return NO_ERROR;
75 }
76
OperationRateManager(ExynosPrimaryDisplay * display,int32_t hsHz,int32_t nsHz)77 ExynosPrimaryDisplayModule::OperationRateManager::OperationRateManager(
78 ExynosPrimaryDisplay* display, int32_t hsHz, int32_t nsHz)
79 : gs201::ExynosPrimaryDisplayModule::OperationRateManager(),
80 mDisplay(display),
81 mDisplayHsOperationRate(hsHz),
82 mDisplayNsOperationRate(nsHz),
83 mDisplayPeakRefreshRate(0),
84 mDisplayRefreshRate(0),
85 mDisplayLastDbv(0),
86 mDisplayDbv(0),
87 mDisplayPowerMode(HWC2_POWER_MODE_ON),
88 mDisplayLowBatteryModeEnabled(false) {
89 mDisplayNsMinDbv = property_get_int32("vendor.primarydisplay.op.ns_min_dbv", 0);
90 mDisplayTargetOperationRate = mDisplayHsOperationRate;
91 OP_MANAGER_LOGI("Op Rate: NS=%d HS=%d NsMinDbv=%d", mDisplayNsOperationRate,
92 mDisplayHsOperationRate, mDisplayNsMinDbv);
93 }
94
~OperationRateManager()95 ExynosPrimaryDisplayModule::OperationRateManager::~OperationRateManager() {}
96
onPeakRefreshRate(uint32_t rate)97 int32_t ExynosPrimaryDisplayModule::OperationRateManager::onPeakRefreshRate(uint32_t rate) {
98 Mutex::Autolock lock(mLock);
99 char rateStr[PROP_VALUE_MAX];
100 std::sprintf(rateStr, "%d", rate);
101
102 OP_MANAGER_LOGD("rate=%d", rate);
103 mDisplayPeakRefreshRate = rate;
104 if (property_set("persist.vendor.primarydisplay.op.peak_refresh_rate", rateStr) < 0) {
105 OP_MANAGER_LOGE("failed to set property persist.primarydisplay.op.peak_refresh_rate");
106 }
107 return 0;
108 }
109
onLowPowerMode(bool enabled)110 int32_t ExynosPrimaryDisplayModule::OperationRateManager::onLowPowerMode(bool enabled) {
111 Mutex::Autolock lock(mLock);
112 OP_MANAGER_LOGD("enabled=%d", enabled);
113 mDisplayLowBatteryModeEnabled = enabled;
114 return 0;
115 }
116
onConfig(hwc2_config_t cfg)117 int32_t ExynosPrimaryDisplayModule::OperationRateManager::onConfig(hwc2_config_t cfg) {
118 Mutex::Autolock lock(mLock);
119 mDisplayRefreshRate = mDisplay->getRefreshRate(cfg);
120 OP_MANAGER_LOGD("rate=%d", mDisplayRefreshRate);
121 updateOperationRateLocked(DispOpCondition::SET_CONFIG);
122 return 0;
123 }
124
onBrightness(uint32_t dbv)125 int32_t ExynosPrimaryDisplayModule::OperationRateManager::onBrightness(uint32_t dbv) {
126 Mutex::Autolock lock(mLock);
127 if (dbv == 0 || mDisplayLastDbv == dbv) return 0;
128 OP_MANAGER_LOGD("dbv=%d", dbv);
129 mDisplayDbv = dbv;
130
131 /*
132 Update peak_refresh_rate from persist/vendor prop after a brightness change.
133 1. Otherwise there will be NS-HS-NS switch during the onPowerMode.
134 2. When constructor is called, persist property is not ready yet and returns 0.
135 */
136 if (!mDisplayPeakRefreshRate) {
137 char rateStr[PROP_VALUE_MAX];
138 int32_t vendorPeakRefreshRate = 0, persistPeakRefreshRate = 0;
139 if (property_get("persist.vendor.primarydisplay.op.peak_refresh_rate", rateStr, "0") >= 0 &&
140 atoi(rateStr) > 0) {
141 persistPeakRefreshRate = atoi(rateStr);
142 mDisplayPeakRefreshRate = persistPeakRefreshRate;
143 } else {
144 vendorPeakRefreshRate =
145 property_get_int32("vendor.primarydisplay.op.peak_refresh_rate", 0);
146 mDisplayPeakRefreshRate = vendorPeakRefreshRate;
147 }
148
149 OP_MANAGER_LOGD("peak_refresh_rate=%d[vendor: %d|persist %d]", mDisplayPeakRefreshRate,
150 vendorPeakRefreshRate, persistPeakRefreshRate);
151 }
152
153 return updateOperationRateLocked(DispOpCondition::SET_DBV);
154 }
155
onPowerMode(int32_t mode)156 int32_t ExynosPrimaryDisplayModule::OperationRateManager::onPowerMode(int32_t mode) {
157 std::string modeName = "Unknown";
158 if (mode == HWC2_POWER_MODE_ON) {
159 modeName = "On";
160 } else if (mode == HWC2_POWER_MODE_OFF) {
161 modeName = "Off";
162 } else if (mode == HWC2_POWER_MODE_DOZE || mode == HWC2_POWER_MODE_DOZE_SUSPEND) {
163 modeName = "LP";
164 }
165
166 Mutex::Autolock lock(mLock);
167 OP_MANAGER_LOGD("mode=%s", modeName.c_str());
168 mDisplayPowerMode = static_cast<hwc2_power_mode_t>(mode);
169 return updateOperationRateLocked(DispOpCondition::PANEL_SET_POWER);
170 }
171
updateOperationRateLocked(const DispOpCondition cond)172 int32_t ExynosPrimaryDisplayModule::OperationRateManager::updateOperationRateLocked(
173 const DispOpCondition cond) {
174 int32_t ret = HWC2_ERROR_NONE, dbv;
175
176 ATRACE_CALL();
177 if (cond == DispOpCondition::SET_DBV) {
178 dbv = mDisplayDbv;
179 } else {
180 dbv = mDisplayLastDbv;
181 }
182
183 int32_t desiredOpRate = mDisplayHsOperationRate;
184 int32_t curRefreshRate = mDisplay->getRefreshRate(mDisplay->mActiveConfig);
185 bool isSteadyLowRefreshRate =
186 (mDisplayPeakRefreshRate && mDisplayPeakRefreshRate <= mDisplayNsOperationRate) ||
187 mDisplayLowBatteryModeEnabled;
188 int32_t effectiveOpRate = 0;
189
190 // check minimal operation rate needed
191 if (isSteadyLowRefreshRate && curRefreshRate <= mDisplayNsOperationRate) {
192 desiredOpRate = mDisplayNsOperationRate;
193 }
194 // check blocking zone
195 if (dbv < mDisplayNsMinDbv) {
196 desiredOpRate = mDisplayHsOperationRate;
197 }
198
199 if (mDisplayPowerMode == HWC2_POWER_MODE_DOZE ||
200 mDisplayPowerMode == HWC2_POWER_MODE_DOZE_SUSPEND) {
201 mDisplayTargetOperationRate = LP_OP_RATE;
202 desiredOpRate = mDisplayTargetOperationRate;
203 effectiveOpRate = desiredOpRate;
204 } else if (mDisplayPowerMode != HWC2_POWER_MODE_ON) {
205 return ret;
206 }
207
208 if (cond == DispOpCondition::SET_CONFIG) {
209 curRefreshRate = mDisplayRefreshRate;
210 if ((curRefreshRate > mDisplayNsOperationRate) &&
211 (curRefreshRate <= mDisplayHsOperationRate))
212 effectiveOpRate = mDisplayHsOperationRate;
213 } else if (cond == DispOpCondition::PANEL_SET_POWER) {
214 if (mDisplayPowerMode == HWC2_POWER_MODE_ON) {
215 mDisplayTargetOperationRate = getTargetOperationRate();
216 }
217 effectiveOpRate = desiredOpRate;
218 } else if (cond == DispOpCondition::SET_DBV) {
219 // TODO: tune brightness delta for different brightness curve and values
220 int32_t delta = abs(dbv - mDisplayLastDbv);
221 if ((desiredOpRate == mDisplayHsOperationRate) || (delta > BRIGHTNESS_DELTA_THRESHOLD)) {
222 effectiveOpRate = desiredOpRate;
223 }
224 mDisplayLastDbv = dbv;
225 if (effectiveOpRate > LP_OP_RATE && (effectiveOpRate != mDisplayTargetOperationRate)) {
226 OP_MANAGER_LOGD("brightness delta=%d", delta);
227 } else {
228 return ret;
229 }
230 }
231
232 if (!mDisplay->isConfigSettingEnabled() && effectiveOpRate == mDisplayNsOperationRate) {
233 OP_MANAGER_LOGI("rate switching is disabled, skip NS op rate update");
234 return ret;
235 } else if (effectiveOpRate > LP_OP_RATE) {
236 ret = setTargetOperationRate(effectiveOpRate);
237 }
238
239 OP_MANAGER_LOGI("Target@%d(desired:%d) | Refresh@%d(peak:%d), Battery:%s, DBV:%d(NsMin:%d)",
240 mDisplayTargetOperationRate, desiredOpRate, curRefreshRate,
241 mDisplayPeakRefreshRate, mDisplayLowBatteryModeEnabled ? "Low" : "OK",
242 mDisplayLastDbv, mDisplayNsMinDbv);
243 return ret;
244 }
245
checkPreblendingRequirement()246 void ExynosPrimaryDisplayModule::checkPreblendingRequirement() {
247 if (!hasDisplayColor()) {
248 DISPLAY_LOGD(eDebugTDM, "%s is skipped because of no displaycolor", __func__);
249 return;
250 }
251
252 String8 log;
253 int count = 0;
254
255 auto checkPreblending = [&](const int idx, ExynosMPPSource* mppSrc) -> int {
256 auto* colorManager = getColorManager();
257 if (!colorManager) return false;
258 auto& dpp = colorManager->getDppForLayer(mppSrc);
259 mppSrc->mNeedPreblending =
260 dpp.EotfLut().enable | dpp.Gm().enable | dpp.Dtm().enable | dpp.OetfLut().enable;
261 if (hwcCheckDebugMessages(eDebugTDM)) {
262 log.appendFormat(" i=%d,pb(%d-%d,%d,%d,%d)", idx, mppSrc->mNeedPreblending,
263 dpp.EotfLut().enable, dpp.Gm().enable, dpp.Dtm().enable,
264 dpp.OetfLut().enable);
265 }
266 return mppSrc->mNeedPreblending;
267 };
268
269 // for client target
270 count += checkPreblending(-1, &mClientCompositionInfo);
271
272 // for normal layers
273 for (size_t i = 0; i < mLayers.size(); ++i) {
274 count += checkPreblending(i, mLayers[i]);
275 }
276 DISPLAY_LOGD(eDebugTDM, "disp(%d),cnt=%d%s", mDisplayId, count, log.c_str());
277 }
278