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