• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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