summaryrefslogtreecommitdiff
path: root/common/hwc/ActiveModeMgr.cpp (plain)
blob: 2d6cf78203c9ed614ceb480eb51459f92d2d1402
1/*
2 * Copyright (c) 2018 Amlogic, Inc. All rights reserved.
3 *
4 * This source code is subject to the terms and conditions defined in the
5 * file 'LICENSE' which is part of this source code package.
6 *
7 * Description:
8 */
9
10#include "ActiveModeMgr.h"
11#include <HwcConfig.h>
12#include <MesonLog.h>
13#include <systemcontrol.h>
14#include <hardware/hwcomposer2.h>
15
16#include <string>
17#include <math.h>
18
19
20#define DEFUALT_DPI (160)
21#define DEFAULT_REFRESH_RATE_60 (60.0f)
22#define DEFAULT_REFRESH_RATE_50 (50.0f)
23
24#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
25
26/* used for init default configs */
27static const drm_mode_info_t mode_info[] = {
28 { /* VMODE_720P */
29 .name = "720p60hz",
30 .dpiX = DEFUALT_DPI,
31 .dpiY = DEFUALT_DPI,
32 .pixelW = 1280,
33 .pixelH = 720,
34 .refreshRate = DEFAULT_REFRESH_RATE_60,
35 },
36 { /* VMODE_1080P */
37 .name = "1080p60hz",
38 .dpiX = DEFUALT_DPI,
39 .dpiY = DEFUALT_DPI,
40 .pixelW = 1920,
41 .pixelH = 1080,
42 .refreshRate = DEFAULT_REFRESH_RATE_60,
43 },
44 { /* VMODE_720P_50hz */
45 .name = "720p50hz",
46 .dpiX = DEFUALT_DPI,
47 .dpiY = DEFUALT_DPI,
48 .pixelW = 1280,
49 .pixelH = 720,
50 .refreshRate = DEFAULT_REFRESH_RATE_50,
51 },
52 { /* VMODE_1080P_50HZ */
53 .name = "1080p50hz",
54 .dpiX = DEFUALT_DPI,
55 .dpiY = DEFUALT_DPI,
56 .pixelW = 1920,
57 .pixelH = 1080,
58 .refreshRate = DEFAULT_REFRESH_RATE_50,
59 },
60 { /* DefaultMode */
61 .name = "DefaultMode",
62 .dpiX = DEFUALT_DPI,
63 .dpiY = DEFUALT_DPI,
64 .pixelW = 1920,
65 .pixelH = 1080,
66 .refreshRate = DEFAULT_REFRESH_RATE_60,
67 },
68};
69
70ActiveModeMgr::ActiveModeMgr()
71 : mIsInit(true) {
72}
73
74ActiveModeMgr::~ActiveModeMgr() {
75
76}
77
78hwc_modes_policy_t ActiveModeMgr::getPolicyType() {
79 return ACTIVE_MODE_POLICY;
80}
81
82const char * ActiveModeMgr::getName() {
83 return "ActiveMode";
84}
85
86void ActiveModeMgr::setFramebufferSize(uint32_t w, uint32_t h) {
87 mFbWidth = w;
88 mFbHeight = h;
89}
90
91void ActiveModeMgr::setDisplayResources(
92 std::shared_ptr<HwDisplayCrtc> & crtc,
93 std::shared_ptr<HwDisplayConnector> & connector) {
94 mConnector = connector;
95 mCrtc = crtc;
96
97 /*
98 * Only when it is first boot will come here,
99 * initialize a default display mode according to the given FB size,
100 * and will return this default mode to SF before it calls setActiveConfig().
101 */
102 if (mIsInit) {
103 mIsInit = false;
104 reset();
105 initDefaultDispResources();
106 }
107}
108
109int32_t ActiveModeMgr::initDefaultDispResources() {
110 mDefaultMode =
111 findMatchedMode(mFbWidth, mFbHeight, DEFAULT_REFRESH_RATE_60);
112 mHwcActiveModes.emplace(mHwcActiveModes.size(), mDefaultMode);
113 updateHwcActiveConfig(mDefaultMode.name);
114 MESON_LOGV("initDefaultDispResources (%s)", mDefaultMode.name);
115 return 0;
116}
117
118int32_t ActiveModeMgr::update() {
119 MESON_LOG_FUN_ENTER();
120 useFakeMode = false;
121 if (mConnector->isConnected()) {
122 //buidl config lists for hwc and sf
123 drm_mode_info_t dispmode;
124 int32_t rnt;
125 rnt = getDisplayMode(dispmode);
126 MESON_LOGD("ActiveModeMgr::update() dispmode.name [%s] mExtModeSet:%d rnt %d", dispmode.name, mExtModeSet, rnt);
127 if (rnt == 0) {
128 if (!mExtModeSet) {
129 updateHwcDispConfigs();
130 updateSfDispConfigs();
131 }
132 } else {
133 useFakeMode = true;
134 MESON_LOGD("Get invalid display mode.");
135 }
136 } else
137 useFakeMode = true;
138
139 if (useFakeMode)
140 updateHwcActiveConfig(mDefaultMode.name);
141
142 MESON_LOG_FUN_LEAVE();
143 return 0;
144}
145
146int32_t ActiveModeMgr::getDisplayMode(drm_mode_info_t & mode) {
147 return mCrtc->getMode(mode);
148}
149
150int32_t ActiveModeMgr::getDisplayConfigs(
151 uint32_t * outNumConfigs, uint32_t * outConfigs) {
152 *outNumConfigs = mSfActiveModes.size();
153 MESON_LOGD("ActiveModeMgr::getDisplayConfigs(a,b)");
154 if (outConfigs) {
155 updateSfDispConfigs();
156 std::map<uint32_t, drm_mode_info_t>::iterator it =
157 mSfActiveModes.begin();
158 for (uint32_t index = 0; it != mSfActiveModes.end(); ++it, ++index) {
159 outConfigs[index] = it->first;
160 MESON_LOGV("outConfig[%d]: %d.", index, outConfigs[index]);
161 }
162 }
163 return HWC2_ERROR_NONE;
164}
165
166
167bool ActiveModeMgr::isFracRate(float refreshRate) {
168 return refreshRate > floor(refreshRate) ? true : false;
169}
170
171int32_t ActiveModeMgr::updateHwcDispConfigs() {
172 std::map<uint32_t, drm_mode_info_t> supportedModes;
173 drm_mode_info_t activeMode;
174 mHwcActiveModes.clear();
175 mHwcActiveConfigId = -1;
176 MESON_LOGD("ActiveModeMgr::updateHwcDispConfigs()");
177
178 mConnector->getModes(supportedModes);
179 if (mCrtc->getMode(activeMode) != 0) {
180 activeMode = mDefaultMode;
181 }
182 mActiveConfigStr = activeMode.name;
183
184 for (auto it = supportedModes.begin(); it != supportedModes.end(); ++it) {
185 MESON_LOGV("[%s]: add Hwc modes %s.", __func__, it->second.name);
186 mHwcActiveModes.emplace(mHwcActiveModes.size(), it->second);
187
188 if (!strncmp(activeMode.name, it->second.name, DRM_DISPLAY_MODE_LEN) &&
189 activeMode.refreshRate == it->second.refreshRate) {
190 mHwcActiveConfigId = mHwcActiveModes.size() - 1;
191 mActiveConfigStr = activeMode.name;
192 }
193 }
194
195 mConnector->setMode(activeMode);
196
197 if (mHwcActiveModes.empty()) {
198 mHwcActiveModes.emplace(mHwcActiveModes.size(), mDefaultMode);
199 mHwcActiveConfigId = mHwcActiveModes.size() - 1;
200 }
201
202 MESON_LOGD("[%s]: updateHwcDispConfigs Hwc active modes %s. refreshRate %f",
203 __func__, activeMode.name, activeMode.refreshRate);
204 return HWC2_ERROR_NONE;
205}
206
207int32_t ActiveModeMgr::updateSfDispConfigs() {
208 // clear display modes
209 mSfActiveModes.clear();
210 mSfActiveConfigId = -1;
211
212 std::map<uint32_t, drm_mode_info_t> mTmpModes;
213 mTmpModes = mHwcActiveModes;
214
215 MESON_LOGD("ActiveModeMgr::updateSfDispConfigs()");
216
217 std::map<float, drm_mode_info_t> tmpList;
218 std::map<float, drm_mode_info_t>::iterator tmpIt;
219
220 for (auto it = mTmpModes.begin(); it != mTmpModes.end(); ++it) {
221 //first check the fps, if there is not the same fps, add it to sf list
222 //then check the width, add the biggest width one.
223 drm_mode_info_t cfg = it->second;
224 std::string cMode = cfg.name;
225 float cFps = cfg.refreshRate;
226 uint32_t cWidth = cfg.pixelW;
227
228 tmpIt = tmpList.find(cFps);
229 if (tmpIt != tmpList.end()) {
230 drm_mode_info_t iCfg = tmpIt->second;
231 uint32_t iWidth = iCfg.pixelW;
232 if ((cWidth >= iWidth) && (cWidth != 4096)) {
233 tmpList.erase(tmpIt);
234 tmpList.emplace(cFps, it->second);
235 }
236 } else {
237 tmpList.emplace(cFps, it->second);
238 }
239 }
240
241 for (tmpIt = tmpList.begin(); tmpIt != tmpList.end(); ++tmpIt) {
242 mSfActiveModes.emplace(mSfActiveModes.size(), tmpIt->second);
243
244 auto it = mHwcActiveModes.find(mHwcActiveConfigId);
245 if (it != mHwcActiveModes.end()) {
246 if (!strncmp(it->second.name, tmpIt->second.name, DRM_DISPLAY_MODE_LEN)
247 && it->second.refreshRate == tmpIt->second.refreshRate) {
248 mSfActiveConfigId = mSfActiveModes.size() - 1;
249 MESON_LOGD("curMode: %s", mActiveConfigStr.c_str());
250 }
251 }
252 }
253
254 MESON_LOGD("update Sf list with no default mode done, size (%zu)", mSfActiveModes.size());
255
256 mFakeConfigId = mSfActiveConfigId;
257 return HWC2_ERROR_NONE;
258}
259
260int32_t ActiveModeMgr::getDisplayAttribute(
261 uint32_t config, int32_t attribute, int32_t * outValue, int32_t caller __unused) {
262/* MESON_LOGV("getDisplayAttribute: config %d, fakeConfig %d,"
263 "HwcActiveConfig %d, SfActiveConfig %d, mExtModeSet %d, caller (%s)",
264 config, mFakeConfigId, mHwcActiveConfigId, mSfActiveConfigId, mExtModeSet,
265 caller == CALL_FROM_SF ? "SF" : "HWC");*/
266
267 std::map<uint32_t, drm_mode_info_t>::iterator it;
268 it = mSfActiveModes.find(config);
269 if (it != mSfActiveModes.end()) {
270 drm_mode_info_t curMode = it->second;
271 switch (attribute) {
272 case HWC2_ATTRIBUTE_WIDTH:
273 *outValue = mDefaultMode.pixelW;
274 break;
275 case HWC2_ATTRIBUTE_HEIGHT:
276 *outValue = mDefaultMode.pixelH;
277 break;
278 case HWC2_ATTRIBUTE_VSYNC_PERIOD:
279 #ifdef HWC_HEADLESS
280 *outValue = 1e9 / (HWC_HEADLESS_REFRESHRATE);
281 #else
282 *outValue = 1e9 / curMode.refreshRate;
283 #endif
284 break;
285 case HWC2_ATTRIBUTE_DPI_X:
286 *outValue = curMode.dpiX * 1000.0f;
287 break;
288 case HWC2_ATTRIBUTE_DPI_Y:
289 *outValue = curMode.dpiY * 1000.0f;
290 break;
291 default:
292 MESON_LOGE("Unkown display attribute(%d)", attribute);
293 break;
294 }
295 return HWC2_ERROR_NONE;
296 }
297 else {
298 MESON_LOGE("[%s]: no support display config: %d", __func__, config);
299 return HWC2_ERROR_UNSUPPORTED;
300 }
301}
302
303int32_t ActiveModeMgr::updateHwcActiveConfig(
304 const char * activeMode) {
305 MESON_LOGD("ActiveModeMgr::updateHwcActiveConfig (mode)");
306 for (auto it = mHwcActiveModes.begin(); it != mHwcActiveModes.end(); ++it) {
307 if (strncmp(activeMode, it->second.name, DRM_DISPLAY_MODE_LEN) == 0
308 && !isFracRate(it->second.refreshRate)) {
309 mDefaultModeSupport = true;
310 mHwcActiveConfigId = mHwcActiveModes.size()-1;
311 MESON_LOGD("updateActiveConfig to (%s, %d)", activeMode, mHwcActiveConfigId);
312 return HWC2_ERROR_NONE;
313 }
314 }
315
316 mHwcActiveConfigId = mHwcActiveModes.size()-1;
317 MESON_LOGD("updateActiveConfig something error to (%s, %d)", activeMode, mHwcActiveConfigId);
318
319 return HWC2_ERROR_NONE;
320}
321
322
323int32_t ActiveModeMgr::updateSfActiveConfig(
324 uint32_t configId, drm_mode_info_t cfg) {
325 mActiveConfigStr = cfg.name;
326 mSfActiveConfigId = configId;
327 mFakeConfigId = mSfActiveModes.size()-1;
328 MESON_LOGD("updateSfActiveConfig(mode) to (%s, %d)", cfg.name, mSfActiveConfigId);
329 return HWC2_ERROR_NONE;
330}
331
332int32_t ActiveModeMgr::getActiveConfig(
333 uint32_t * outConfig, int32_t caller __unused) {
334 *outConfig = mExtModeSet ? mSfActiveConfigId : mFakeConfigId;
335/* MESON_LOGV("[%s]: ret %d, Sf id %d, Hwc id %d, fake id %d, mExtModeSet %d, caller (%s)",
336 __func__ ,*outConfig, mSfActiveConfigId, mHwcActiveConfigId, mFakeConfigId,
337 mExtModeSet, caller == CALL_FROM_SF ? "SF" : "HWC");*/
338 return HWC2_ERROR_NONE;
339}
340
341int32_t ActiveModeMgr::setActiveConfig(
342 uint32_t configId) {
343 std::map<uint32_t, drm_mode_info_t>::iterator it =
344 mSfActiveModes.find(configId);
345 MESON_LOGD("ActiveModeMgr::setActiveConfig %d", configId);
346 if (it != mSfActiveModes.end()) {
347 drm_mode_info_t cfg = it->second;
348
349 // update real active config.
350 updateSfActiveConfig(configId, cfg);
351
352 // It is possible that default mode is not supported by the sink
353 // and it was only advertised to the FWK to force 1080p UI.
354 // Trap this case and do nothing. FWK will keep thinking
355 // 1080p is supported and set.
356 if (!mDefaultModeSupport
357 && strncmp(cfg.name, mDefaultMode.name, DRM_DISPLAY_MODE_LEN) == 0) {
358 MESON_LOGD("setActiveConfig default mode not supported");
359 return HWC2_ERROR_NONE;
360 }
361
362 mExtModeSet = true;
363 mCallOnHotPlug = false;
364 mConnector->setMode(cfg);
365 mCrtc->setMode(cfg);
366 MESON_LOGD("setActiveConfig %d, mExtModeSet %d",
367 configId, mExtModeSet);
368 return HWC2_ERROR_NONE;
369 } else {
370 MESON_LOGE("set invalild active config (%d)", configId);
371 return HWC2_ERROR_NOT_VALIDATED;
372 }
373}
374
375void ActiveModeMgr::reset() {
376 mHwcActiveModes.clear();
377 mSfActiveModes.clear();
378 mDefaultModeSupport = false;
379 mSfActiveConfigId = mHwcActiveConfigId = mFakeConfigId = -1;
380 mExtModeSet = false;
381 mCallOnHotPlug = true;
382}
383
384void ActiveModeMgr::resetTags() {
385 if (!useFakeMode) {
386 mCallOnHotPlug = true;
387 mExtModeSet = false;
388 }
389};
390
391
392const drm_mode_info_t ActiveModeMgr::findMatchedMode(
393 uint32_t width, uint32_t height, float refreshrate) {
394 uint32_t i = 0;
395 uint32_t size = ARRAY_SIZE(mode_info);
396 for (i = 0; i < size; i++) {
397 if (mode_info[i].pixelW == width &&
398 mode_info[i].pixelH == height &&
399 mode_info[i].refreshRate == refreshrate) {
400 return mode_info[i];
401 }
402 }
403 return mode_info[size-1];
404}
405
406void ActiveModeMgr::dump(String8 & dumpstr) {
407 dumpstr.appendFormat("ActiveModeMgr: %s\n", mActiveConfigStr.c_str());
408 dumpstr.append("---------------------------------------------------------"
409 "-------------------------------------------------\n");
410 dumpstr.append("| CONFIG | VSYNC_PERIOD | WIDTH | HEIGHT |"
411 " DPI_X | DPI_Y | FRAC | mode \n");
412 dumpstr.append("+------------+------------------+-----------+------------+"
413 "-----------+-----------+-----------+-----------+\n");
414 std::map<uint32_t, drm_mode_info_t>::iterator it =
415 mHwcActiveModes.begin();
416 for (; it != mHwcActiveModes.end(); ++it) {
417 int mode = it->first;
418 drm_mode_info_t config = it->second;
419 dumpstr.appendFormat("%s %2d | %.3f | %5d | %5d |"
420 " %3d | %3d | %d | %s \n",
421 (mode == (int)mHwcActiveConfigId) ? "* " : " ",
422 mode,
423 config.refreshRate,
424 config.pixelW,
425 config.pixelH,
426 config.dpiX,
427 config.dpiY,
428 isFracRate(config.refreshRate),
429 config.name);
430 }
431 dumpstr.append("---------------------------------------------------------"
432 "-------------------------------------------------\n");
433
434 dumpstr.appendFormat("ActiveModeMgr: %s\n", mActiveConfigStr.c_str());
435 dumpstr.append("---------------------------------------------------------"
436 "-------------------------------------------------\n");
437 dumpstr.append("| CONFIG | VSYNC_PERIOD | WIDTH | HEIGHT |"
438 " DPI_X | DPI_Y | FRAC | mode \n");
439 dumpstr.append("+------------+------------------+-----------+------------+"
440 "-----------+-----------+-----------+-----------+\n");
441 std::map<uint32_t, drm_mode_info_t>::iterator it1 =
442 mSfActiveModes.begin();
443 for (; it1 != mSfActiveModes.end(); ++it1) {
444 int mode1 = it1->first;
445 drm_mode_info_t config = it1->second;
446 dumpstr.appendFormat("%s %2d | %.3f | %5d | %5d |"
447 " %3d | %3d | %d | %s \n",
448 (mode1 == (int)mSfActiveConfigId) ? "* " : " ",
449 mode1,
450 config.refreshRate,
451 config.pixelW,
452 config.pixelH,
453 config.dpiX,
454 config.dpiY,
455 isFracRate(config.refreshRate),
456 config.name);
457 }
458 dumpstr.append("---------------------------------------------------------"
459 "-------------------------------------------------\n");
460}
461
462