summaryrefslogtreecommitdiff
path: root/hwc2/common/hdmi/DisplayHdmi.cpp (plain)
blob: 76b9e3dab28877668b4dcfc10cfb431d7f89482f
1/*
2// Copyright (c) 2017 Amlogic
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
18//#define LOG_NDEBUG 0
19#include <HwcTrace.h>
20#include <binder/IServiceManager.h>
21#include <utils/Tokenizer.h>
22#include "DisplayHdmi.h"
23#include <cutils/properties.h>
24
25namespace android {
26namespace amlogic {
27
28#define DEFAULT_DISPMODE "1080p60hz"
29#define DEFAULT_DISPLAY_DPI 160
30
31DisplayHdmi::DisplayHdmi()
32 : mFirstBootup(true)
33{
34 if (Utils::get_bool_prop("ro.sf.full_activemode")) {
35 mWorkMode = REAL_ACTIVEMODE;
36 } else {
37 mWorkMode = NONE_ACTIVEMODE;
38 }
39}
40
41DisplayHdmi::~DisplayHdmi() {
42}
43
44auto DisplayHdmi::getSystemControlService() {
45 static bool bGot = false;
46
47#if PLATFORM_SDK_VERSION >= 26
48 static auto systemControl = ISystemControl::getService();
49
50 if (bGot)
51 return systemControl;
52 mDeathRecipient = new SystemControlDeathRecipient();
53 Return<bool> linked = systemControl->linkToDeath(mDeathRecipient, /*cookie*/ 0);
54 if (!linked.isOk()) {
55 ETRACE("Transaction error in linking to system service death: %s", linked.description().c_str());
56 } else if (!linked) {
57 ETRACE("Unable to link to system service death notifications");
58 } else {
59 ITRACE("Link to system service death notification successful");
60 }
61
62#else
63 sp<IServiceManager> sm = defaultServiceManager();
64 if (sm == NULL) {
65 ETRACE("Couldn't get default ServiceManager\n");
66 return NULL;
67 }
68 static auto systemControl = interface_cast<ISystemControlService>(sm->getService(String16("system_control")));
69
70 if (bGot)
71 return systemControl;
72
73 if (systemControl == NULL) {
74 ETRACE("Couldn't get connection to SystemControlService\n");
75 return NULL;
76 }
77
78
79#endif
80
81 bGot = true;
82 return systemControl;
83}
84
85void DisplayHdmi::initialize(framebuffer_info_t& framebufferInfo) {
86 reset();
87 std::string dispMode;
88 calcDefaultMode(framebufferInfo, dispMode);
89 buildSingleConfigList(dispMode);
90 updateActiveConfig(dispMode);
91
92 mFbWidth = framebufferInfo.info.xres;
93 mFbHeight = framebufferInfo.info.yres;
94}
95
96void DisplayHdmi::deinitialize() {
97 reset();
98}
99
100void DisplayHdmi::reset() {
101 clearSupportedConfigs();
102 mActiveConfigStr.clear();
103 mConnected = false;
104 mActiveConfigId = mRealActiveConfigId = VMODE_NULL;
105 mPhyWidth = mPhyHeight = 0;
106}
107
108bool DisplayHdmi::updateHotplug(bool connected,
109 framebuffer_info_t& framebufferInfo) {
110 bool ret = true;
111 int32_t rate;
112 mConnected = connected;
113
114 if (!connected) {
115 DTRACE("hdmi disconnected, keep old display configs.");
116 return true;
117 }
118
119 updateDisplayAttributes(framebufferInfo);
120
121 std::string activemode;
122 if (readHdmiDispMode(activemode) != HWC2_ERROR_NONE) {
123 ETRACE("get active display mode failed.");
124 return false;
125 }
126
127 if (updateSupportedConfigs() != HWC2_ERROR_NONE) {
128 ETRACE("updateHotplug: No supported display list, set default configs.");
129 std::string dM (DEFAULT_DISPMODE);
130 buildSingleConfigList(dM);
131 }
132 updateActiveConfig(activemode);
133 // setBestDisplayMode();
134
135 return true;
136}
137
138int DisplayHdmi::updateSupportedConfigs() {
139 // clear display modes
140 clearSupportedConfigs();
141
142 std::vector<std::string> supportDispModes;
143 std::string::size_type pos;
144 std::string dM (DEFAULT_DISPMODE);
145
146 bool isConfiged = readConfigFile("/system/etc/displayModeList.cfg", &supportDispModes);
147 if (isConfiged) {
148 DTRACE("Read supported modes from cfg file.");
149 } else {
150 if (mWorkMode == NONE_ACTIVEMODE) {
151 DTRACE("Simple Active Mode!!!");
152 return BAD_VALUE;
153 }
154
155 readEdidList(supportDispModes);
156 if (supportDispModes.size() == 0) {
157 ETRACE("SupportDispModeList null!!!");
158 return BAD_VALUE;
159 }
160 }
161
162 for (size_t i = 0; i < supportDispModes.size(); i++) {
163 if (!supportDispModes[i].empty()) {
164 pos = supportDispModes[i].find('*');
165 if (pos != std::string::npos) {
166 supportDispModes[i].erase(pos, 1);
167 DTRACE("modify support display mode:%s", supportDispModes[i].c_str());
168 }
169
170 // skip default / fake active mode as we add it to the end
171 if (supportDispModes[i] != dM)
172 addSupportedConfig(supportDispModes[i]);
173 }
174 }
175
176 addSupportedConfig(dM);
177 return NO_ERROR;
178}
179
180int DisplayHdmi::buildSingleConfigList(std::string& defaultMode) {
181 if (!isDispModeValid(defaultMode)) {
182 ETRACE("buildSingleConfigList with invalidate mode (%s)", defaultMode.c_str());
183 return false;
184 }
185
186 return addSupportedConfig(defaultMode);
187}
188
189int DisplayHdmi::calcDefaultMode(framebuffer_info_t& framebufferInfo,
190 std::string& defaultMode) {
191 const struct vinfo_s * mode =
192 findMatchedMode(framebufferInfo.info.xres, framebufferInfo.info.yres, 60);
193 if (mode == NULL) {
194 defaultMode = DEFAULT_DISPMODE;
195 } else {
196 defaultMode = mode->name;
197 }
198
199 defaultMode = DEFAULT_DISPMODE;
200
201 DTRACE("calcDefaultMode %s", defaultMode.c_str());
202 return NO_ERROR;
203}
204
205int DisplayHdmi::addSupportedConfig(std::string& mode) {
206 vmode_e vmode = vmode_name_to_mode(mode.c_str());
207 const struct vinfo_s* vinfo = get_tv_info(vmode);
208 if (vmode == VMODE_MAX || vinfo == NULL) {
209 ETRACE("addSupportedConfig meet error mode (%s, %d)", mode.c_str(), vmode);
210 return BAD_VALUE;
211 }
212
213 int dpiX = DEFAULT_DISPLAY_DPI, dpiY = DEFAULT_DISPLAY_DPI;
214 if (mPhyWidth > 16 && mPhyHeight > 9) {
215 dpiX = (vinfo->width * 25.4f) / mPhyWidth;
216 dpiY = (vinfo->height * 25.4f) / mPhyHeight;
217 }
218
219 DisplayConfig *config = new DisplayConfig(mode,
220 vinfo->sync_duration_num,
221 vinfo->width,
222 vinfo->height,
223 dpiX,
224 dpiY,
225 false);
226
227 // add normal refresh rate config, like 24hz, 30hz...
228 DTRACE("add display mode pair (%d, %s)", mSupportDispConfigs.size(), mode.c_str());
229 mSupportDispConfigs.add(mSupportDispConfigs.size(), config);
230
231 if (mWorkMode == REAL_ACTIVEMODE) {
232 // add frac refresh rate config, like 23.976hz, 29.97hz...
233 if (vinfo->sync_duration_num == REFRESH_24kHZ
234 || vinfo->sync_duration_num == REFRESH_30kHZ
235 || vinfo->sync_duration_num == REFRESH_60kHZ
236 || vinfo->sync_duration_num == REFRESH_120kHZ
237 || vinfo->sync_duration_num == REFRESH_240kHZ) {
238 DisplayConfig *fracConfig = new DisplayConfig(mode,
239 vinfo->sync_duration_num,
240 vinfo->width,
241 vinfo->height,
242 dpiX,
243 dpiY,
244 true);
245 mSupportDispConfigs.add(mSupportDispConfigs.size(), fracConfig);
246 }
247 }
248
249 return NO_ERROR;
250}
251
252int DisplayHdmi::updateActiveConfig(std::string& activeMode) {
253 mRealActiveConfigStr = activeMode;
254 for (size_t i = 0; i < mSupportDispConfigs.size(); i++) {
255 DisplayConfig * cfg = mSupportDispConfigs.valueAt(i);
256 if (activeMode == cfg->getDisplayMode()) {
257 mRealActiveConfigId = mSupportDispConfigs.keyAt(i);
258 DTRACE("updateRealActiveConfig to (%s, %d)", activeMode.c_str(), mRealActiveConfigId);
259 }
260 }
261 mActiveConfigId = mSupportDispConfigs.size()-1;
262 return NO_ERROR;
263}
264
265status_t DisplayHdmi::setBestDisplayMode() {
266 std::string bM;
267
268 readBestHdmiOutputMode(bM);
269 if (mRealActiveConfigStr.compare(bM) || mFirstBootup) {
270 DTRACE("setBestDisplayMode to %s", bM.c_str());
271 setDisplayMode(bM);
272 }
273 // update real active config.
274 updateActiveConfig(bM);
275
276 if (mFirstBootup) mFirstBootup = false;
277 return NO_ERROR;
278}
279
280void DisplayHdmi::switchRatePolicy(bool fracRatePolicy) {
281/*
282TODO: need add new api for hdmi frac rate policy.
283*/
284#if 0
285 auto scs = getSystemControlService();
286 if (scs == NULL) {
287 ETRACE("switchRatePolicy FAIL.");
288 return;
289 }
290
291 if (fracRatePolicy) {
292 if (scs->writeSysfs(String16(HDMI_FRAC_RATE_POLICY), String16("1")))
293 ETRACE("Switch to frac rate policy SUCCESS.");
294 else
295 ETRACE("Switch to frac rate policy FAIL.");
296 } else {
297 if (scs->writeSysfs(String16(HDMI_FRAC_RATE_POLICY), String16("0")))
298 ETRACE("Switch to normal rate policy SUCCESS.");
299 else
300 ETRACE("Switch to normal rate policy FAIL.");
301 }
302#endif
303}
304
305int DisplayHdmi::setDisplayMode(std::string& dm, bool policy) {
306 DTRACE("setDisplayMode to %s", dm.c_str());
307 switchRatePolicy(policy);
308 writeHdmiDispMode(dm);
309 updateActiveConfig(dm);
310 return NO_ERROR;
311}
312
313status_t DisplayHdmi::readHdmiPhySize(framebuffer_info_t& fbInfo) {
314 struct fb_var_screeninfo vinfo;
315 if ((fbInfo.fd >= 0) && (ioctl(fbInfo.fd, FBIOGET_VSCREENINFO, &vinfo) == 0)) {
316 if (int32_t(vinfo.width) > 16 && int32_t(vinfo.height) > 9) {
317 mPhyWidth = vinfo.width;
318 mPhyHeight = vinfo.height;
319 }
320 return NO_ERROR;
321 }
322 return BAD_VALUE;
323}
324
325int DisplayHdmi::updateDisplayAttributes(framebuffer_info_t& framebufferInfo) {
326 if (readHdmiPhySize(framebufferInfo) != NO_ERROR) {
327 mPhyWidth = mPhyHeight = 0;
328 }
329 DTRACE("updateDisplayAttributes physical size (%d x %d)", mPhyWidth, mPhyHeight);
330 return NO_ERROR;
331}
332
333int DisplayHdmi::getDisplayConfigs(uint32_t* outNumConfigs,
334 hwc2_config_t* outConfigs) {
335 size_t i;
336
337 if (!isConnected()) {
338 ETRACE("hdmi is not connected.");
339 }
340
341 size_t configsNum = mSupportDispConfigs.size();
342 *outNumConfigs = configsNum;
343 if (NULL != outConfigs) {
344 for (i = 0; i < configsNum; i++) {
345 outConfigs[i] = mSupportDispConfigs.keyAt(i);
346 }
347 }
348
349 return NO_ERROR;
350}
351
352int DisplayHdmi::getDisplayAttribute(hwc2_config_t config,
353 int32_t /*hwc2_attribute_t*/ attribute,
354 int32_t* outValue) {
355 if (!isConnected()) {
356 ETRACE("hdmi is not connected.");
357 }
358
359 DisplayConfig *configChosen = NULL;
360 int modeIdx = mSupportDispConfigs.indexOfKey((vmode_e)config);
361 if (modeIdx >= 0)
362 configChosen = mSupportDispConfigs.valueAt(modeIdx);
363 if (!configChosen) {
364 ETRACE("failed to get display config: %d", config);
365 return BAD_VALUE;
366 }
367
368 switch (attribute) {
369 case HWC2_ATTRIBUTE_VSYNC_PERIOD:
370 if (mWorkMode == REAL_ACTIVEMODE) {
371 if (configChosen->getRefreshRate()) {
372 *outValue = 1e9 / configChosen->getRefreshRate();
373 }
374 } else if (mWorkMode == LOGIC_ACTIVEMODE ||
375 mWorkMode == NONE_ACTIVEMODE) {
376 *outValue = 1e9 / 60;
377 }
378 break;
379 case HWC2_ATTRIBUTE_WIDTH:
380 if (mWorkMode == REAL_ACTIVEMODE) {
381 *outValue = configChosen->getWidth();
382 } else if (mWorkMode == LOGIC_ACTIVEMODE ||
383 mWorkMode == NONE_ACTIVEMODE) {
384 *outValue = mFbWidth;
385 }
386 break;
387 case HWC2_ATTRIBUTE_HEIGHT:
388 if (mWorkMode == REAL_ACTIVEMODE) {
389 *outValue = configChosen->getHeight();
390 } else if (mWorkMode == LOGIC_ACTIVEMODE ||
391 mWorkMode == NONE_ACTIVEMODE) {
392 *outValue = mFbHeight;
393 }
394 break;
395 case HWC2_ATTRIBUTE_DPI_X:
396 *outValue = configChosen->getDpiX() * 1000.0f;
397 break;
398 case HWC2_ATTRIBUTE_DPI_Y:
399 *outValue = configChosen->getDpiY() * 1000.0f;
400 break;
401 default:
402 ETRACE("unknown display attribute %u", attribute);
403 *outValue = -1;
404 break;
405 }
406
407 return NO_ERROR;
408}
409
410int DisplayHdmi::getActiveConfig(hwc2_config_t* outConfig) {
411 if (!isConnected()) {
412 ETRACE("hdmi is not connected.");
413 }
414 // DTRACE("getActiveConfig to config(%d).", mActiveConfigId);
415 *outConfig = mActiveConfigId;
416 return NO_ERROR;
417}
418
419int DisplayHdmi::getRealActiveConfig(hwc2_config_t* outConfig) {
420 if (!isConnected()) {
421 ETRACE("hdmi is not connected.");
422 }
423 // DTRACE("getActiveConfig to config(%d).", mActiveConfigId);
424 *outConfig = mRealActiveConfigId;
425 return NO_ERROR;
426}
427
428int DisplayHdmi::setActiveConfig(int modeId) {
429 if (!isConnected()) {
430 ETRACE("hdmi display is not connected.");
431 }
432
433 DTRACE("setActiveConfig to mode(%d).", modeId);
434 int modeIdx = mSupportDispConfigs.indexOfKey((const vmode_e)modeId);
435 if (modeIdx >= 0) {
436 DisplayConfig* cfg = mSupportDispConfigs.valueAt(modeIdx);
437 std::string dM = cfg->getDisplayMode();
438
439 DTRACE("setActiveConfig to (%d, %s).", modeId, dM.c_str());
440 setDisplayMode(dM, cfg->getFracRatePolicy());
441
442 // update real active config.
443 updateActiveConfig(dM);
444 return NO_ERROR;
445 } else {
446 ETRACE("set invalild active config (%d)", modeId);
447 return BAD_VALUE;
448 }
449}
450
451bool DisplayHdmi::readConfigFile(const char* configPath, std::vector<std::string>* supportDispModes) {
452 const char* WHITESPACE = " \t\r";
453
454 Tokenizer* tokenizer;
455 status_t status = Tokenizer::open(String8(configPath), &tokenizer);
456
457 if (status) {
458 DTRACE("Error %d opening display config file %s.", status, configPath);
459 return false;
460 } else {
461 while (!tokenizer->isEof()) {
462 tokenizer->skipDelimiters(WHITESPACE);
463 if (!tokenizer->isEol() && tokenizer->peekChar() != '#') {
464 String8 token = tokenizer->nextToken(WHITESPACE);
465 const char* dispMode = token.string();
466 if (strstr(dispMode, "hz")) {
467 ETRACE("dispMode %s.", dispMode);
468 (*supportDispModes).push_back(std::string(dispMode));
469 }
470 }
471
472 tokenizer->nextLine();
473 }
474 delete tokenizer;
475 }
476
477 size_t num = (*supportDispModes).size();
478
479 if (num <= 0) {
480 return false;
481 } else {
482 return true;
483 }
484}
485
486int DisplayHdmi::clearSupportedConfigs() {
487 // reset display configs
488 for (size_t i = 0; i < mSupportDispConfigs.size(); i++) {
489 DisplayConfig *config = mSupportDispConfigs.valueAt(i);
490 if (config)
491 delete config;
492 }
493 mSupportDispConfigs.clear();
494 return NO_ERROR;
495}
496
497bool DisplayHdmi::chkPresent() {
498 bool bConnect = false;
499 std::string dispMode;
500 if (!readHdmiDispMode(dispMode)) {
501 bConnect = isDispModeValid(dispMode);
502 }
503
504 DTRACE("chkPresent %s", bConnect ? "connected" : "disconnected");
505 return bConnect;
506}
507
508bool DisplayHdmi::isDispModeValid(std::string & dispmode){
509 if (dispmode.empty())
510 return false;
511
512 vmode_e mode = vmode_name_to_mode(dispmode.c_str());
513 // DTRACE("isDispModeValid get mode (%d)", mode);
514 if (mode == VMODE_MAX)
515 return false;
516
517 if (want_hdmi_mode(mode) == 0)
518 return false;
519
520 return true;
521}
522
523int DisplayHdmi::readHdmiDispMode(std::string &dispmode) {
524 auto scs = getSystemControlService();
525 if (scs == NULL) {
526 ETRACE("syscontrol::readHdmiDispMode FAIL.");
527 return FAILED_TRANSACTION;
528 }
529
530#if PLATFORM_SDK_VERSION >= 26
531 scs->getActiveDispMode([&dispmode](const Result &ret, const hidl_string& mode) {
532 if (Result::OK == ret) {
533 dispmode = mode.c_str();
534 } else {
535 dispmode.clear();
536 }
537 });
538
539 if (dispmode.empty()) {
540 ETRACE("syscontrol::getActiveDispMode FAIL.");
541 return FAILED_TRANSACTION;
542 }
543#else
544 if (scs->getActiveDispMode(&dispmode)) {
545 } else {
546 ETRACE("syscontrol::getActiveDispMode FAIL.");
547 return FAILED_TRANSACTION;
548 }
549#endif
550
551 DTRACE("get current displaymode %s", dispmode.c_str());
552 if (!isDispModeValid(dispmode)) {
553 DTRACE("active mode %s not valid", dispmode.c_str());
554 return BAD_VALUE;
555 }
556
557 return NO_ERROR;
558}
559
560int DisplayHdmi::writeHdmiDispMode(std::string &dispmode) {
561 auto scs = getSystemControlService();
562 if (scs == NULL) {
563 ETRACE("syscontrol::writeHdmiDispMode FAIL.");
564 return FAILED_TRANSACTION;
565 }
566
567#if PLATFORM_SDK_VERSION >= 26
568 Result rtn = scs->setActiveDispMode(dispmode);
569 if (rtn == Result::OK) {
570 return NO_ERROR;
571 }
572#else
573 if (scs->setActiveDispMode(dispmode)) {
574 return NO_ERROR;
575 }
576#endif
577
578 ETRACE("syscontrol::setActiveDispMode FAIL.");
579 return FAILED_TRANSACTION;
580}
581
582int DisplayHdmi::readEdidList(std::vector<std::string>& edidlist) {
583 auto scs = getSystemControlService();
584 if (scs == NULL) {
585 ETRACE("syscontrol::readEdidList FAIL.");
586 return FAILED_TRANSACTION;
587 }
588
589#if PLATFORM_SDK_VERSION >= 26
590 scs->getSupportDispModeList([&edidlist](const Result &ret, const hidl_vec<hidl_string> supportDispModes) {
591 if (Result::OK == ret) {
592 for (size_t i = 0; i < supportDispModes.size(); i++) {
593 edidlist.push_back(supportDispModes[i]);
594 }
595 } else {
596 edidlist.clear();
597 }
598 });
599
600 if (edidlist.empty()) {
601 ETRACE("syscontrol::readEdidList FAIL.");
602 return FAILED_TRANSACTION;
603 }
604
605 return NO_ERROR;
606#else
607 if (scs->getSupportDispModeList(&edidlist)) {
608 return NO_ERROR;
609 } else {
610 ETRACE("syscontrol::readEdidList FAIL.");
611 return FAILED_TRANSACTION;
612 }
613#endif
614}
615
616int DisplayHdmi::readBestHdmiOutputMode(std::string &dispmode) {
617#if 0
618 auto scs = getSystemControlService();
619 if (scs == NULL) {
620 ETRACE("syscontrol::readEdidList FAIL.");
621 return FAILED_TRANSACTION;
622 }
623
624 if (scs->getBestHdmiOutputMode(&dispmode)) {
625 DTRACE("get best displaymode %s", dispmode.c_str());
626 if (!isDispModeValid(dispmode)) {
627 ETRACE("best mode %s not valid", dispmode.c_str());
628 return BAD_VALUE;
629 }
630 return NO_ERROR;
631 }
632#endif
633
634 return NO_ERROR;
635}
636
637bool DisplayHdmi::isSecure() {
638 auto scs = getSystemControlService();
639 if (scs == NULL) {
640 ETRACE("syscontrol::isHDCPTxAuthSuccess FAIL.");
641 return false;
642 }
643
644#if PLATFORM_SDK_VERSION >= 26
645 Result rtn = scs->isHDCPTxAuthSuccess();
646 DTRACE("hdcp status: %d", status);
647 return rtn == Result::OK ? true : false;
648#else
649 int status = 0;
650 scs->isHDCPTxAuthSuccess(status);
651 DTRACE("hdcp status: %d", status);
652 return status == 1 ? true : false;
653#endif
654
655}
656
657void DisplayHdmi::dump(Dump& d) {
658 d.append("Connector (HDMI, %s, %d, %d)\n",
659 mRealActiveConfigStr.c_str(),
660 mRealActiveConfigId,
661 mWorkMode);
662 d.append(" CONFIG | VSYNC_PERIOD | WIDTH | HEIGHT |"
663 " DPI_X | DPI_Y \n");
664 d.append("------------+------------------+-----------+------------+"
665 "-----------+-----------\n");
666 for (size_t i = 0; i < mSupportDispConfigs.size(); i++) {
667 int mode = mSupportDispConfigs.keyAt(i);
668 DisplayConfig *config = mSupportDispConfigs.valueAt(i);
669 if (config) {
670 d.append("%s %2d | %.3f | %5d | %5d |"
671 " %3d | %3d \n",
672 (mode == (int)mActiveConfigId) ? "* " : " ",
673 mode,
674 config->getRefreshRate(),
675 config->getWidth(),
676 config->getHeight(),
677 config->getDpiX(),
678 config->getDpiY());
679 }
680 }
681 }
682
683} // namespace amlogic
684} // namespace android
685
686
687
688