blob: da65cca314cadc3c3532e707d81ed97def995666 [file] [log] [blame]
leng.fang91856072024-06-07 14:12:54 +08001/*
2 * Copyright (c) 2022 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 "ModePolicy.h"
11#include "mode_ubootenv.h"
12#include <inttypes.h>
13#include <sys/utsname.h>
14#include <memory>
15//#include <systemcontrol.h>
16static int g_activeLevel= 3;
17
18/* testing if tv support this displaymode and deepcolor combination, then if cat result is 1: support, 0: not */
19#define DISPLAY_HDMI_VALID_MODE "/sys/class/amhdmitx/amhdmitx0/valid_mode"
20
21#define PROP_DEFAULT_COLOR "ro_vendor_platform_default_color"
22#define LOW_POWER_DEFAULT_COLOR "ro_vendor_low_power_default_color" /* Set default deep color is 8bit for Low Power Mode */
23#define UBOOTENV_COLORATTRIBUTE "ubootenv.var.colorattribute"
24
25#define EDID_MAX_SIZE 2049
26#define MODE_8K4K_PREFIX "4320p"
27#define PROP_VALUE_MAX 92
28
leng.fang91856072024-06-07 14:12:54 +080029enum {
30 DISPLAY_TYPE_NONE = 0,
31 DISPLAY_TYPE_TABLET = 1,
32 DISPLAY_TYPE_MBOX = 2,
33 DISPLAY_TYPE_TV = 3,
34 DISPLAY_TYPE_REPEATER = 4
35};
36
leng.fang91856072024-06-07 14:12:54 +080037static const char* AMDV_MODE_TYPE[] = {
38 "DV_RGB_444_8BIT",
39 "DV_YCbCr_422_12BIT",
40 "LL_YCbCr_422_12BIT",
41 "LL_RGB_444_10BIT",
42 "LL_RGB_444_12BIT"
43};
44
45static const char* ALLM_MODE_CAP[] = {
46 "0",
47 "1",
48};
49
50static const char* ALLM_MODE[] = {
51 "-1",
52 "0",
53 "1",
54};
55
56static const char* CONTENT_TYPE_CAP[] = {
57 "graphics",
58 "photo",
59 "cinema",
60 "game",
61};
62
63/*****************************************/
64/* deepcolor */
65
66//this is check hdmi mode(4K60/4k50) list
67static const char* COLOR_ATTRIBUTE_LIST[] = {
68 COLOR_RGB_8BIT,
69 COLOR_YCBCR444_8BIT,
70 COLOR_YCBCR420_8BIT,
71 COLOR_YCBCR422_8BIT,
72};
73
74//this is check hdmi mode list
75static const char* COLOR_ATTRIBUTE_LIST_8BIT[] = {
76 COLOR_RGB_8BIT,
77 COLOR_YCBCR444_8BIT,
78 COLOR_YCBCR422_8BIT,
79};
80
81std::shared_ptr<ModePolicy> g_Policy;
82std::shared_ptr<DisplayAdapter> g_Adapter;
83
84ModePolicy::ModePolicy() {
85 mDisplayType = DISPLAY_TYPE_MBOX;
86 mPolicy = MESON_POLICY_MIX;
87 mReason = OUTPUT_CHANGE_BY_INIT;
88 mDisplayId = 0;
89 memset(&mConnectorType, 0, sizeof(mConnectorType));
90 memset(&mModeConType, 0, sizeof(mModeConType));
91 memset(&mConData, 0, sizeof(mConData));
92 memset(&mSceneOutInfo, 0, sizeof(mSceneOutInfo));
93 memset(&mState, 0, sizeof(mState));
94 memset(&mDvInfo, 0, sizeof(mDvInfo));
95 mDisplayWidth = 0;
96 mDisplayHeight = 0;
97 mFracMode = MODE_FRACTION;
leng.fangc81d8672024-07-11 10:14:46 +080098 mEnvLock = PTHREAD_MUTEX_INITIALIZER;
leng.fang91856072024-06-07 14:12:54 +080099}
100
101ModePolicy::ModePolicy(std::shared_ptr<DisplayAdapter> adapter, const uint32_t displayId) {
102 mAdapter = adapter;
103 mDisplayType = DISPLAY_TYPE_MBOX;
104 mPolicy = MESON_POLICY_MIX;
105 mReason = OUTPUT_CHANGE_BY_INIT;
106 mDisplayId = displayId;
107 memset(&mConnectorType, 0, sizeof(mConnectorType));
108 memset(&mModeConType, 0, sizeof(mModeConType));
109 memset(&mConData, 0, sizeof(mConData));
110 memset(&mSceneOutInfo, 0, sizeof(mSceneOutInfo));
111 memset(&mState, 0, sizeof(mState));
112 memset(&mDvInfo, 0, sizeof(mDvInfo));
113 mDisplayWidth = 0;
114 mDisplayHeight = 0;
115 mFracMode = MODE_FRACTION;
leng.fangc81d8672024-07-11 10:14:46 +0800116 mEnvLock = PTHREAD_MUTEX_INITIALIZER;
leng.fang91856072024-06-07 14:12:54 +0800117}
118
119ModePolicy::~ModePolicy() {
120
121}
122
123bool ModePolicy::getBootEnv(const char *key, char *value) {
124 const char* p_value;
125 const char* envName = key;
126 if (strstr(key, PROFIX_UBOOTENV_VAR) != NULL)
127 envName = key + strlen(PROFIX_UBOOTENV_VAR);
128 p_value = bootenv_get(envName);
129 MESON_LOGD("get key:%s value:%s", key, p_value ? p_value : "novalue");
130
131 if (p_value) {
132 strcpy(value, p_value);
133 return true;
134 }
135
136 return false;
137}
138
139int ModePolicy::getBootenvInt(const char* key, int defaultVal) {
140 int value = defaultVal;
141 const char* p_value;
142 const char* envName = key;
143 if (strstr(key, PROFIX_UBOOTENV_VAR) != NULL)
144 envName = key + strlen(PROFIX_UBOOTENV_VAR);
145 p_value = bootenv_get(envName);
146 if (p_value) {
147 value = atoi(p_value);
148 }
149 return value;
150}
151
152void ModePolicy::setBootEnv(const char* key, const char* value) {
leng.fang13fd3982024-07-03 19:09:58 +0800153 const char* p_value;
leng.fang91856072024-06-07 14:12:54 +0800154 const char* envName = key;
155 if (strstr(key, PROFIX_UBOOTENV_VAR) != NULL)
156 envName = key + strlen(PROFIX_UBOOTENV_VAR);
leng.fang13fd3982024-07-03 19:09:58 +0800157 p_value = bootenv_get(envName);
158
159 if (p_value && !strcmp(p_value, value)) {
160 MESON_LOGV("value is equal, do not set");
161 return;
162 }
163
164 MESON_LOGD("set key:%s value:%s", key, value);
leng.fang91856072024-06-07 14:12:54 +0800165 bootenv_update(envName, value);
166}
167
168
169// TODO: need refactor
170#ifdef HDR_AMDV_PROPERTY
171void ModePolicy::getDvCap(struct meson_hdr_info *data) {
172 if (!data) {
173 MESON_LOGE("%s data is NULL\n", __FUNCTION__);
174 return;
175 }
176
177 std::string amdv_cap;
178 int cap = 0;
179 getDisplayAttribute(DISPLAY_AMDV_CAP, amdv_cap);
180 strcpy(data->dv_cap, amdv_cap.c_str());
181 cap = atoi(data->dv_cap);
182
183 if (cap != 0) {
184 uint32_t index = (cap & (1 << 2)) ? 19 : 17;
185 if ((strlen(data->dv_max_mode) + strlen(DISPLAY_MODE_LIST[index]) + 1) < sizeof(data->dv_max_mode)) {
186 strcat(data->dv_max_mode, DISPLAY_MODE_LIST[index]);
187 strcat(data->dv_max_mode, ",");
188 } else {
189 MESON_LOGE("DisplayMode strcat overflow: src=%s, dst=%s\n", DISPLAY_MODE_LIST[index], data->dv_max_mode);
190 }
191
192 index = ((cap & 0xf8) >> 3);
193 for (int i = 0; i < ARRAY_SIZE(AMDV_MODE_TYPE); i++) {
194 if (index & (1 << i)) {
195 strcat(data->dv_deepcolor, AMDV_MODE_TYPE[i]);
196 strcat(data->dv_deepcolor, ",");
197 }
198 }
199 }
200}
201#else
202void ModePolicy::getDvCap(struct meson_hdr_info *data) {
203 if (!data) {
204 MESON_LOGE("%s data is NULL\n", __FUNCTION__);
205 return;
206 }
207
208 std::string amdv_cap;
209 getDisplayAttribute(DISPLAY_AMDV_CAP2, amdv_cap);
210 strcpy(data->dv_cap, amdv_cap.c_str());
211
212 if (strstr(data->dv_cap, "DolbyVision RX support list") != NULL) {
213 memset(data->dv_max_mode, 0, sizeof(data->dv_max_mode));
214 memset(data->dv_deepcolor, 0, sizeof(data->dv_deepcolor));
215 for (int i = ARRAY_SIZE(DISPLAY_MODE_LIST) - 1; i >= 0; i--) {
216 if (strstr(data->dv_cap, DISPLAY_MODE_LIST[i]) != NULL) {
217 if ((strlen(data->dv_max_mode) + strlen(DISPLAY_MODE_LIST[i]) + 1) < sizeof(data->dv_max_mode)) {
218 strcpy(data->dv_max_mode, DISPLAY_MODE_LIST[i]);
219 } else {
220 MESON_LOGE("DisplayMode strcat overflow: src=%s, dst=%s\n", DISPLAY_MODE_LIST[i], data->dv_max_mode);
221 }
222 break;
223 }
224 }
225
226 for (int i = 0; i < sizeof(AMDV_MODE_TYPE)/sizeof(AMDV_MODE_TYPE[0]); i++) {
227 if (strstr(data->dv_cap, AMDV_MODE_TYPE[i])) {
228 if ((strlen(data->dv_deepcolor) + strlen(AMDV_MODE_TYPE[i]) + 2) < sizeof(data->dv_deepcolor)) {
229 strcat(data->dv_deepcolor, AMDV_MODE_TYPE[i]);
230 strcat(data->dv_deepcolor, ",");
231 } else {
232 MESON_LOGE("DisplayMode strcat overflow: src=%s, dst=%s\n", AMDV_MODE_TYPE[i], data->dv_deepcolor);
233 break;
234 }
235 }
236 }
237 MESON_LOGI("TV dv info: mode:%s deepcolor: %s\n", data->dv_max_mode, data->dv_deepcolor);
238 } else {
239 MESON_LOGE("TV isn't support dv: %s\n", data->dv_cap);
240 }
241}
242#endif
243
244void ModePolicy::getHdmiDcCap(char* dc_cap, int32_t len) {
245 if (!dc_cap) {
246 MESON_LOGE("%s dc_cap is NULL\n", __FUNCTION__);
247 return;
248 }
249
250 int count = 0;
251 while (true) {
252 sysfs_get_string_original(DISPLAY_HDMI_DEEP_COLOR, dc_cap, len);
253 if (strlen(dc_cap) > 0)
254 break;
255
256 if (count >= 5) {
257 MESON_LOGE("read dc_cap fail\n");
258 break;
259 }
260 count++;
261 usleep(500000);
262 }
263}
264
265int ModePolicy::getHdmiSinkType() {
266 char sinkType[MESON_MODE_LEN] = {0};
267 if (sysfs_get_string(DISPLAY_HDMI_SINK_TYPE, sinkType, MESON_MODE_LEN) != 0)
268 return HDMI_SINK_TYPE_NONE;
269
270 if (NULL != strstr(sinkType, "sink")) {
271 return HDMI_SINK_TYPE_SINK;
272 } else if (NULL != strstr(sinkType, "repeater")) {
273 return HDMI_SINK_TYPE_REPEATER;
274 } else {
275 return HDMI_SINK_TYPE_NONE;
276 }
277}
278
279void ModePolicy::getHdmiEdidStatus(char* edidstatus, int32_t len) {
280 if (!edidstatus) {
281 MESON_LOGE("%s edidstatus is NULL\n", __FUNCTION__);
282 return;
283 }
284
285 sysfs_get_string(DISPLAY_EDID_STATUS, edidstatus, len);
286}
287
288int32_t ModePolicy::setHdrStrategy(int32_t policy, const char *type) {
289 SYS_LOGI("%s type:%s policy:%s", __func__,
290 meson_hdrPolicyToString(policy), type);
291
292 //1. update env policy
293 std::string value = std::to_string(policy);
294 setBootEnv(UBOOTENV_HDR_POLICY, value.c_str());
295
296 if (policy == MESON_HDR_POLICY_SOURCE) {
297 if (isDVEnable()) {
298 setBootEnv(UBOOTENV_DOLBYSTATUS, "0");
299 }
300 } else {
301 char dvstatus[MESON_MODE_LEN] = {0};
302 if (isDVEnable()) {
leng.fangd8ab2872024-06-28 16:23:43 +0800303 sprintf(dvstatus, "%d", mSceneOutInfo.amdv_type);
leng.fang91856072024-06-07 14:12:54 +0800304 setBootEnv(UBOOTENV_DOLBYSTATUS, dvstatus);
305 }
306 }
307
308 int32_t priority = MESON_HDR10_PRIORITY;
309 value = std::to_string(MESON_HDR10_PRIORITY);
310 if (strstr(type, AMDV_DISABLE_FORCE_SDR)) {
311 priority = MESON_SDR_PRIORITY;
312 value = std::to_string(MESON_SDR_PRIORITY);
313 }
314
315 //2. set current hdmi mode
316 meson_mode_set_policy_input(mModeConType, &mConData);
317 getDisplayMode(mCurrentMode);
318
319 if (!meson_mode_support_mode(mModeConType, priority, mCurrentMode)) {
320 setBootEnv(UBOOTENV_HDR_FORCE_MODE, type);
321 setSourceOutputMode(mCurrentMode);
322 } else {
323 MESON_LOGD("%s mode check failed", __func__);
324 return -EINVAL;
325 }
326
327 return 0;
328}
329
330void ModePolicy::getHdrStrategy(char* value) {
331 char hdr_policy[MESON_MODE_LEN] = {0};
332
333 memset(hdr_policy, 0, MESON_MODE_LEN);
334 getBootEnv(UBOOTENV_HDR_POLICY, hdr_policy);
335
336 if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) {
337 strcpy(value, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
338 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) {
339 strcpy(value, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
340 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE])) {
341 strcpy(value, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]);
342 } else if (strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) {
343 strcpy(value, AMDV_POLICY_FORCE_MODE);
344 }
345 MESON_LOGI("get uboot HdrStrategy is [%s]", value);
346}
347
348int32_t ModePolicy::setHdrPriority(int32_t type) {
349 MESON_LOGI("setHdrPriority is [%s]\n", meson_hdrPriorityToString(type));
350
351 meson_mode_set_policy_input(mModeConType, &mConData);
352 getDisplayMode(mCurrentMode);
353
354 if (!meson_mode_support_mode(mModeConType, type, mCurrentMode)) {
355 std::string value = std::to_string(type);
356
357 setSourceOutputMode(mCurrentMode);
358 } else {
359 MESON_LOGD("%s mode check failed", __func__);
360 return -EINVAL;
361 }
362
363 return 0;
364}
365
366int32_t ModePolicy::getHdrPriority() {
367 char hdr_priority[MESON_MODE_LEN] = {0};
368 meson_hdr_priority_e value = MESON_DOLBY_VISION_PRIORITY;
369
370 memset(hdr_priority, 0, MESON_MODE_LEN);
371 getBootEnv(UBOOTENV_HDR_PRIORITY, hdr_priority);
372
373 value = (meson_hdr_priority_e)atoi(hdr_priority);
374 if ((value >= MESON_DOLBY_VISION_PRIORITY && value <= MESON_SDR_PRIORITY)
375 || (value >= MESON_G_DV_HDR10_HLG && value <= MESON_G_SDR)) {
376 MESON_LOGI("%s is [%s]", __FUNCTION__, meson_hdrPriorityToString(value));
377 } else {
378 MESON_LOGE("%s [%d] is invalid", __FUNCTION__, value);
379 }
380
381 MESON_LOGI("get uboot HdrPriority is [%s]", meson_hdrPriorityToString(value));
382 return (int32_t)value;
383}
384
385int32_t ModePolicy::getCurrentHdrPriority(void) {
386 meson_hdr_priority_e value = MESON_DOLBY_VISION_PRIORITY;
387
388 std::string cur_hdr_priority;
389 getDisplayAttribute(DISPLAY_HDR_PRIORITY, cur_hdr_priority);
390
391 value = (meson_hdr_priority_e)atoi(cur_hdr_priority.c_str());
392 if ((value >= MESON_DOLBY_VISION_PRIORITY && value <= MESON_SDR_PRIORITY)
393 || (value >= MESON_G_DV_HDR10_HLG && value <= MESON_G_SDR)) {
394 MESON_LOGI("%s is [%s]", __FUNCTION__, meson_hdrPriorityToString(value));
395 } else {
396 MESON_LOGE("%s [%d] is invalid", __FUNCTION__, value);
397 }
398
399 return (int32_t)value;
400}
401
402void ModePolicy::gethdrforcemode(char* value) {
403 if (!value) {
404 MESON_LOGE("%s value is NULL\n", __FUNCTION__);
405 return;
406 }
407
408 bool ret = false;
409 char hdr_force_mode[MESON_MODE_LEN] = {0};
410
411 memset(hdr_force_mode, 0, MESON_MODE_LEN);
412 ret = getBootEnv(UBOOTENV_HDR_FORCE_MODE, hdr_force_mode);
413 if (ret) {
414 strcpy(value, hdr_force_mode);
415 } else {
416 strcpy(value, FORCE_AMDV);
417 }
418
419 MESON_LOGI("get hdr force mode is [%s]", value);
420}
421
422bool ModePolicy::isTvDVEnable() {
423 bool ret = false;
424 char amdv_enable[MESON_MODE_LEN];
425 ret = getBootEnv(UBOOTENV_DV_ENABLE, amdv_enable);
426 if (!ret) {
427 if (isMboxSupportDV()) {
428 strcpy(amdv_enable, "1");
429 } else {
430 strcpy(amdv_enable, "0");
431 }
432 }
433 MESON_LOGI("dv_enable:%s\n", amdv_enable);
434
435 if (!strcmp(amdv_enable, "0")) {
436 return false;
437 } else {
438 return true;
439 }
440}
441
442bool ModePolicy::isDVEnable() {
443 if (isMboxSupportDV() && isTvSupportDV()) {
444 if (!strcmp(mDvInfo.amdv_enable, "0") ) {
445 return false;
446 } else {
447 return true;
448 }
449 } else {
450 return false;
451 }
452}
453
454/* *
455 * @Description: Detect Whether TV support dv
456 * @return: if TV support return true, or false
457 * if true, mode is the Highest resolution Tv dv supported
458 * else mode is ""
459 */
460bool ModePolicy::isTvSupportDV() {
461 if (DISPLAY_TYPE_TV == mDisplayType) {
462 MESON_LOGI("Current Device is TV, no dv_cap\n");
463 return false;
464 }
465
466 if (strstr(mConData.hdr_info.dv_cap, "DolbyVision RX support list") == NULL) {
467 if (atoi(mConData.hdr_info.dv_cap) == 0)
468 return false;
469 }
470
471 return true;
472}
473
474#ifdef HDR_AMDV_PROPERTY
475void ModePolicy::parseHdmiHdrCapabilities(drm_hdr_capabilities & hdrCaps)
476{
477 std::string hdr_cap;
478 int cap = 0;
479 getDisplayAttribute(DISPLAY_HDR_CAP, hdr_cap);
480 MESON_LOGV("parseHdmiHdrCapabilities: hdr cap: %s", hdr_cap.c_str());
481 memset(&hdrCaps, 0, sizeof(drm_hdr_capabilities));
482 cap = atoi(hdr_cap.c_str());
483
484 if (cap & 0x01)
485 hdrCaps.HDR10PlusSupported = true;
486
487 if (cap & (1 << 3))
488 hdrCaps.HDR10Supported = true;
489
490 if (cap & (1 << 4))
491 hdrCaps.HLGSupported = true;
492}
493
494void ModePolicy::parseDvCapabilities()
495{
496 std::string amdv_cap;
497 int cap = 0;
498 getDisplayAttribute(DISPLAY_AMDV_CAP, amdv_cap);
499 MESON_LOGV("parseDvCapabilities: dv cap: %s", amdv_cap.c_str());
500 cap = atoi(amdv_cap.c_str());
501 if (cap != 0 && getDvSupportStatus()) {
502 mHdrCapabilities.DVSupported = true;
503 if ((cap & (1 << 2)) == 0)
504 mHdrCapabilities.AMDV_4K30_Supported = true;
505 }
506}
507#else
508int32_t getLineValue(const char *lineStr, const char *magicStr) {
509 int len = 0;
510 char value[100] = {0};
511 const char *pos = NULL;
512
513 if ((NULL == lineStr) || (NULL == magicStr)) {
514 MESON_LOGE("line string: %s, magic string: %s\n", lineStr, magicStr);
515 return 0;
516 }
517
518 if (NULL != (pos = strstr(lineStr, magicStr))) {
519 pos = pos + strlen(magicStr);
520 const char* start = pos;
521 while ((*start <= '9' && *start >= '0') && (strlen(start) > 0))
522 start++;
523
524 len = start - pos;
525 strncpy(value, pos, len);
526 value[len] = '\0';
527 return atoi(value);
528 }
529
530 return 0;
531}
532
533void ModePolicy::parseHdmiHdrCapabilities(drm_hdr_capabilities & hdrCaps)
534{
535 std::string hdr_cap;
536 char buf[1024 + 1] = { 0 };
537 char* pos = buf;
538
539 getDisplayAttribute(DISPLAY_HDR_CAP2, hdr_cap);
540 MESON_LOGV("parseHdmiHdrCapabilities: hdr cap: %s", hdr_cap.c_str());
541
542 strcpy(buf, hdr_cap.c_str());
543 memset(&hdrCaps, 0, sizeof(drm_hdr_capabilities));
544
545 if (pos != NULL) pos = strstr(pos, "HDR10Plus Supported: ");
546 if ((NULL != pos) && ('1' == *(pos + strlen("HDR10Plus Supported: ")))) {
547 hdrCaps.HDR10PlusSupported = true;
548 }
549
550 if (pos != NULL) pos = strstr(pos, "SMPTE ST 2084: ");
551 if ((NULL != pos) && ('1' == *(pos + strlen("SMPTE ST 2084: ")))) {
552 hdrCaps.HDR10Supported = true;
553
554 hdrCaps.maxLuminance = getLineValue(pos, "Max: ");
555 hdrCaps.avgLuminance = getLineValue(pos, "Avg: ");
556 hdrCaps.minLuminance = getLineValue(pos, "Min: ");
557 }
558
559 if (pos != NULL) {
560 char* hybrif = strstr(pos, "Hybrif Log-Gamma: ");
561 if (NULL != hybrif) {
562 if ('1' == *(hybrif + strlen("Hybrif Log-Gamma: ")))
563 hdrCaps.HLGSupported = true;
564 } else {
565 /* kernel 5.4, content change to: Hybrid Log-Gamma */
566 char* hybrid = strstr(pos, "Hybrid Log-Gamma: ");
567 if ((NULL != hybrid) && ('1' == *(hybrid + strlen("Hybrid Log-Gamma: "))))
568 hdrCaps.HLGSupported = true;
569 }
570 }
571}
572
573void ModePolicy::parseDvCapabilities()
574{
575 std::string amdv_cap;
576 char buf[1024 + 1] = { 0 };
577
578 getDisplayAttribute(DISPLAY_AMDV_CAP2, amdv_cap);
579 MESON_LOGV("parseDvCapabilities: dv cap: %s", amdv_cap.c_str());
580
581 strcpy(buf, amdv_cap.c_str());
582 if (((NULL != strstr(buf, "2160p30hz")) || (NULL != strstr(buf, "2160p60hz"))) &&
583 getDvSupportStatus()) {
584 mHdrCapabilities.DVSupported = true;
585 if (strstr(buf, "2160p30hz"))
586 mHdrCapabilities.AMDV_4K30_Supported = true;
587 } else {
588 mHdrCapabilities.DVSupported = false;
589 }
590}
591#endif
592
593void ModePolicy::updateHdrCaps() {
594 uint32_t type = mConnector ? mConnector->connector_type : 0;
595 bool supportDv = getDvSupportStatus();
596
597 memset(&mHdrCapabilities, 0, sizeof(drm_hdr_capabilities));
598 if (type == DRM_MODE_CONNECTOR_HDMIA) {
599 parseHdmiHdrCapabilities(mHdrCapabilities);
600 parseDvCapabilities();
601 }
602 /* for TV product*/
603 if (type == DRM_MODE_CONNECTOR_MESON_LVDS_A || type == DRM_MODE_CONNECTOR_MESON_LVDS_B ||
604 type == DRM_MODE_CONNECTOR_MESON_LVDS_C || type == DRM_MODE_CONNECTOR_MESON_VBYONE_A ||
605 type == DRM_MODE_CONNECTOR_MESON_VBYONE_B || type == DRM_MODE_CONNECTOR_LVDS) {
606 constexpr int sDefaultMinLumiance = 0;
607 constexpr int sDefaultMaxLumiance = 500;
608
609 mHdrCapabilities.DVSupported = supportDv;
610 mHdrCapabilities.HLGSupported = true;
611 mHdrCapabilities.HDR10Supported = true;
612 mHdrCapabilities.maxLuminance = sDefaultMaxLumiance;
613 mHdrCapabilities.avgLuminance = sDefaultMaxLumiance;
614 mHdrCapabilities.minLuminance = sDefaultMinLumiance;
615 parseDvCapabilities();
616 MESON_LOGD("dv:%d, hlg:%d, hdr10:%d, hdr10+:%d max:%d, avg:%d, min:%d\n",
617 mHdrCapabilities.DVSupported ? 1 : 0,
618 mHdrCapabilities.HLGSupported ? 1 : 0,
619 mHdrCapabilities.HDR10Supported ? 1 : 0,
620 mHdrCapabilities.HDR10PlusSupported ? 1 : 0,
621 mHdrCapabilities.maxLuminance,
622 mHdrCapabilities.avgLuminance,
623 mHdrCapabilities.minLuminance);
624 }
625}
626
627
628void ModePolicy::getHdrCapabilities(drm_hdr_capabilities * caps)
629{
630 if (!caps)
631 return;
632
633 *caps = mHdrCapabilities;
634}
635
636bool ModePolicy::isTvSupportHDR() {
637 if (DISPLAY_TYPE_TV == mDisplayType) {
638 MESON_LOGI("Current Device is TV, no hdr_cap\n");
639 return false;
640 }
641
642 drm_hdr_capabilities hdrCaps;
643 getHdrCapabilities(&hdrCaps);
644
645 if (hdrCaps.HLGSupported ||
646 hdrCaps.HDR10Supported ||
647 hdrCaps.HDR10PlusSupported) {
648 return true;
649 }
650
651 return false;
652}
653
654bool ModePolicy::isHdrResolutionPriority() {
655 return sys_get_bool_prop(PROP_HDR_RESOLUTION_PRIORITY, true);
656}
657
658bool ModePolicy::isFrameratePriority() {
leng.fangd8ab2872024-06-28 16:23:43 +0800659 char frameratePriority[MESON_MODE_LEN] = { 0 };
660
661 if (DISPLAY_TYPE_TV == mDisplayType) {
662 MESON_LOGI("Current Device is TV, no framerate priority\n");
663 return false;
664 }
665 return !getBootEnv(UBOOTENV_FRAMERATE_PRIORITY, frameratePriority) ||
666 strcmp(frameratePriority, "true") == 0;
leng.fang91856072024-06-07 14:12:54 +0800667}
668
669bool ModePolicy::isSupport4K() {
670 return sys_get_bool_prop(PROP_SUPPORT_4K, true);
671}
672
673bool ModePolicy::isSupport4K30Hz() {
674 return sys_get_bool_prop(PROP_SUPPORT_OVER_4K30, true);
675}
676
677bool ModePolicy::isSupportDeepColor() {
678 return sys_get_bool_prop(PROP_DEEPCOLOR, true);
679}
680
681bool ModePolicy::isLowPowerMode() {
682 return sys_get_bool_prop(LOW_POWER_DEFAULT_COLOR, false);
683}
684
685
686bool ModePolicy::isMboxSupportDV() {
687 return getDvSupportStatus();
688}
689
690void ModePolicy::getHdrUserInfo(meson_hdr_info_t *data) {
691 if (!data) {
692 MESON_LOGE("%s data is NULL\n", __FUNCTION__);
693 return;
694 }
695
696 char hdr_force_mode[MESON_MODE_LEN] = {0};
697 gethdrforcemode(hdr_force_mode);
698 data->hdr_force_mode = (meson_hdr_force_mode_e)atoi(hdr_force_mode);
699
700 char hdr_policy[MESON_MODE_LEN] = {0};
701 getHdrStrategy(hdr_policy);
702 data->hdr_policy = (meson_hdr_policy_e)atoi(hdr_policy);
703
704 data->hdr_priority = (meson_hdr_priority_e)getHdrPriority();
705
706 MESON_LOGI("hdr_policy:%d, hdr_priority :%d(0x%x), hdr_force_mode:%d\n",
707 data->hdr_policy,
708 data->hdr_priority, data->hdr_priority,
709 data->hdr_force_mode);
710
711 data->is_amdv_enable = isDVEnable();
712 data->is_tv_supportDv = isTvSupportDV();
713 data->is_tv_supportHDR = isTvSupportHDR();
714 data->is_hdr_resolution_priority = isHdrResolutionPriority();
715 data->is_lowpower_mode = isLowPowerMode();
716
717 char ubootenv_amdv_type[MESON_MODE_LEN];
718 bool ret = getBootEnv(UBOOTENV_USER_DV_TYPE, ubootenv_amdv_type);
719 if (ret) {
720 strcpy(data->ubootenv_dv_type, ubootenv_amdv_type);
721 } else if (isMboxSupportDV()) {
722 strcpy(data->ubootenv_dv_type, "1");
723 } else {
724 strcpy(data->ubootenv_dv_type, "0");
725 }
726 MESON_LOGI("ubootenv_dv_type:%s\n", data->ubootenv_dv_type);
727}
728
729bool ModePolicy::initColorAttribute(char* supportedColorList, int len) {
730 int count = 0;
731 bool result = false;
732
733 if (supportedColorList != NULL) {
734 memset(supportedColorList, 0, len);
735 } else {
736 MESON_LOGE("supportedColorList is NULL\n");
737 return false;
738 }
739
740 while (true) {
741 sysfs_get_string(DISPLAY_HDMI_DEEP_COLOR, supportedColorList, len);
742 if (strlen(supportedColorList) > 0) {
743 result = true;
744 break;
745 }
746
747 if (count++ >= 5) {
748 break;
749 }
750 usleep(500000);
751 }
752
753 return result;
754}
755
756void ModePolicy::setFilterEdidList(std::map<int, std::string> filterEdidList) {
757 MESON_LOGI("FormatColorDepth setFilterEdidList size = %" PRIuFAST16 "", filterEdidList.size());
758 mFilterEdid = filterEdidList;
759}
760
761bool ModePolicy::isFilterEdid() {
762 if (mFilterEdid.empty())
763 return false;
764
765 std::string disPlayEdid = "";
766 getDisplayAttribute(DISPLAY_EDID_ATTR, disPlayEdid);
767 MESON_LOGD("edid property: %s\n", disPlayEdid.c_str());
768
769 for (int i = 0; i < (int)mFilterEdid.size(); i++) {
770 if (!strncmp(mFilterEdid[i].c_str(), disPlayEdid.c_str(), strlen(mFilterEdid[i].c_str()))) {
771 return true;
772 }
773 }
774 return false;
775}
776
777
778bool ModePolicy::isModeSupportDeepColorAttr(const char *mode, const char * color) {
779 char outputmode[MESON_MODE_LEN] = {0};
780
781 strcpy(outputmode, mode);
782 strcat(outputmode, color);
783
784 if (isFilterEdid() && !strstr(color,"8bit")) {
785 MESON_LOGI("this mode has been filtered");
786 return false;
787 }
788
789 //try support or not
790 return sys_set_valid_mode(DISPLAY_HDMI_VALID_MODE, outputmode);
791}
792
793bool ModePolicy::isSupportHdmiMode(const char *hdmi_mode, const char *supportedColorList) {
794 int length = 0;
795 const char **colorList = NULL;
796
797 if (strstr(hdmi_mode, "2160p60hz") != NULL
798 || strstr(hdmi_mode,"2160p50hz") != NULL
799 || strstr(hdmi_mode,"smpte50hz") != NULL
800 || strstr(hdmi_mode,"smpte60hz") != NULL) {
801
802 colorList = COLOR_ATTRIBUTE_LIST;
803 length = ARRAY_SIZE(COLOR_ATTRIBUTE_LIST);
804
805 for (int i = 0; i < length; i++) {
806 if (strstr(supportedColorList, colorList[i]) != NULL) {
807 if (isModeSupportDeepColorAttr(hdmi_mode, colorList[i])) {
808 return true;
809 }
810 }
811 }
812 return false;
813 } else {
814 colorList = COLOR_ATTRIBUTE_LIST_8BIT;
815 length = ARRAY_SIZE(COLOR_ATTRIBUTE_LIST_8BIT);
816
817 for (int j = 0; j < length; j++) {
818 if (strstr(supportedColorList, colorList[j]) != NULL) {
819 if (isModeSupportDeepColorAttr(hdmi_mode, colorList[j])) {
820 return true;
821 }
822 }
823 }
824 return false;
825 }
826}
827
828void ModePolicy::filterHdmiDispcap(meson_connector_info* data) {
829 char supportedColorList[MESON_MAX_STR_LEN];
830
831 if (!(initColorAttribute(supportedColorList, MESON_MAX_STR_LEN))) {
832 MESON_LOGE("initColorAttribute fail\n");
833 return;
834 }
835
836 meson_mode_info_t *modes_ptr = data->modes;
837 for (int i = 0; i < data->modes_size; i++) {
838 meson_mode_info_t *it = &modes_ptr[i];
839 MESON_LOGD("before filtered Hdmi support: %s\n", it->name);
840 if (isSupportHdmiMode(it->name, supportedColorList)) {
841 MESON_LOGD("after filtered Hdmi support mode : %s\n", it->name);
842 }
843 }
844
845}
846
847int32_t ModePolicy::getConnectorData(struct meson_policy_in* data, hdmi_amdv_info_t *dinfo) {
848 if (!data) {
849 MESON_LOGE("%s data is NULL\n", __FUNCTION__);
850 return -EINVAL;
851 }
852
853 getConnectorUserData(data, dinfo);
854
855 //get hdmi dv_info
856 getDvCap(&data->hdr_info);
857
858 // get Hdr info
859 getHdrUserInfo(&data->hdr_info);
860
861 //hdmi info
862 getHdmiEdidStatus(data->con_info.edid_parsing, MESON_MODE_LEN);
863
864 //three sink types: sink, repeater, none
865 data->con_info.sink_type = (meson_sink_type_e)getHdmiSinkType();
866 MESON_LOGI("display sink type:%d [0:none, 1:sink, 2:repeater]\n", data->con_info.sink_type);
867
868 if (HDMI_SINK_TYPE_NONE != data->con_info.sink_type) {
869 getSupportedModes();
870
871 //read hdmi dc_cap
872 char dc_cap[MESON_MAX_STR_LEN];
873 getHdmiDcCap(dc_cap, MESON_MAX_STR_LEN);
874 strcpy(data->con_info.dc_cap, dc_cap);
875 }
876
877 getDisplayMode(data->cur_displaymode);
878
879#if 0
880 //filter hdmi disp_cap mode for compatibility
881 filterHdmiDispcap(&data->con_info);
882#endif
883
884 data->con_info.is_support4k = isSupport4K();
885 data->con_info.is_support4k30HZ = isSupport4K30Hz();
886 data->con_info.is_deepcolor = isSupportDeepColor();
leng.fangd8ab2872024-06-28 16:23:43 +0800887 data->con_info.isframeratepriority = isFrameratePriority();
leng.fang91856072024-06-07 14:12:54 +0800888
889 return 0;
890}
891
892bool ModePolicy::setPolicy(int32_t policy) {
893 MESON_LOGD("setPolicy %d to %d", mPolicy, policy);
894 if (DISPLAY_TYPE_TV == mDisplayType)
895 return true;
896
897 if (mPolicy == policy)
898 return true;
899
900 switch (policy) {
901 case static_cast<int>(MESON_POLICY_BEST):
902 case static_cast<int>(MESON_POLICY_RESOLUTION):
903 case static_cast<int>(MESON_POLICY_FRAMERATE):
904 case static_cast<int>(MESON_POLICY_DV):
leng.fang91856072024-06-07 14:12:54 +0800905 mPolicy = static_cast<meson_mode_policy>(policy);
906 break;
907 default:
908 MESON_LOGE("Set invalid policy:%d", policy);
909 return false;
910 }
911
912 setSourceDisplay(OUTPUT_MODE_STATE_POWER);
913
914 return true;
915}
916
917//TODO:: refactor to a thread to handle hotplug
918void ModePolicy::onHotplug(bool connected) {
919 MESON_LOGD("ModePolicy handle hotplug:%d", connected);
920 //plugout or suspend,set dummy_l
921 if (!connected) {
leng.fang3c0ab6d2024-08-01 16:29:00 +0800922 setDisplay(OUTPUT_MODE_STATE_POWER);
leng.fang91856072024-06-07 14:12:54 +0800923 return;
924 }
925
926 //hdmi edid parse error and hpd = 1
927 //set default reolsution and color format
928 if (isHdmiEdidParseOK() == false) {
929 setDefaultMode();
930 return;
931 }
932
933 //hdmi edid parse ok
934 setSourceDisplay(OUTPUT_MODE_STATE_POWER);
935}
936
937void ModePolicy::setActiveConfig(std::string mode) {
938 mReason = OUTPUT_CHANGE_BY_HWC;
939 MESON_LOGI("setDisplayed by hwc %s", mode.c_str());
940 meson_mode_set_policy(mModeConType, MESON_POLICY_INVALID);
941 setSourceOutputMode(mode.c_str());
942 meson_mode_set_policy(mModeConType, mPolicy);
943 mReason = OUTPUT_CHANGE_BY_INIT;
944}
945
946int32_t ModePolicy::getPreferredBootConfig(std::string &config) {
947 if (DISPLAY_TYPE_TV == mDisplayType) {
948 char curMode[MESON_MODE_LEN] = {0};
949 getDisplayMode(curMode);
950 config = curMode;
951 } else {
952#if 0
953 //1. get hdmi data
954 hdmi_data_t data;
955
956 memset(&data, 0, sizeof(hdmi_data_t));
957 getHdmiData(&data);
958#endif
959 mConData.state = static_cast<meson_mode_state>(OUTPUT_MODE_STATE_INIT);
960 mConData.con_info.is_bestcolorspace = true;
961
962 //2. scene logic process
963 meson_mode_set_policy(mModeConType, MESON_POLICY_RESOLUTION);
964 meson_mode_set_policy_input(mModeConType, &mConData);
965 meson_mode_get_policy_output(mModeConType, &mSceneOutInfo);
966
967 config = mSceneOutInfo.displaymode;
968 }
969
970 MESON_LOGI("getPreferredDisplayConfig [%s]", config.c_str());
971 meson_mode_set_policy(mModeConType, mPolicy);
972 return 0;
973}
974
975int32_t ModePolicy::setBootConfig(std::string &config) {
976 MESON_LOGI("set boot display config to %s\n", config.c_str());
977 setBootEnv(UBOOTENV_ISBESTMODE, "false");
978 if (mConnectorType == CONN_TYPE_HDMI)
979 setBootEnv(UBOOTENV_HDMIMODE, config.c_str());
980
981 return 0;
982}
983
984int32_t ModePolicy::clearBootConfig() {
985 MESON_LOGI("clear boot display \n");
986 setBootEnv(UBOOTENV_ISBESTMODE, "true");
987
988 //save hdmi resolution to env
leng.fang3e8a4b52024-07-24 14:51:30 +0800989 // setBootEnv(UBOOTENV_HDMIMODE, "none");
leng.fang91856072024-06-07 14:12:54 +0800990
991 return 0;
992}
993
994int32_t ModePolicy::clearUserDisplayConfig() {
995 SYS_LOGI("clear user display config\n");
996
997 //clear user color format
998 setBootEnv(UBOOTENV_USER_COLORATTRIBUTE, "none");
999 //clear user dv
1000 setBootEnv(UBOOTENV_USER_DV_TYPE, "none");
1001
1002 //2. set hdmi mode for trigger setting
1003 getDisplayMode(mCurrentMode);
1004 setSourceOutputMode(mCurrentMode);
1005
1006 return 0;
1007}
1008
1009int32_t ModePolicy::setColorSpace(std::string &colorspace) {
1010 SYS_LOGI("user change color space to %s\n", colorspace.c_str());
1011 setBootEnv(UBOOTENV_USER_COLORATTRIBUTE, colorspace.c_str());
1012
1013 getDisplayMode(mCurrentMode);
1014 saveDeepColorAttr(mCurrentMode, colorspace.c_str());
1015
1016 //2. set hdmi mode for trigger setting
1017 setSourceOutputMode(mCurrentMode);
1018
1019 return 0;
1020}
1021
1022void ModePolicy::getModes(drmModeConnector *connector,
1023 std::map<uint32_t, drm_mode_info_t> &modes)
1024{
1025 if (!connector)
1026 return;
1027
1028 if (connector->connection != DRM_MODE_CONNECTED)
1029 return;
1030
1031 mConnecterModes.clear();
1032 /*add new display mode list.*/
1033 drmModeModeInfoPtr drmModes = connector->modes;
1034 drm_mode_info_t modeInfo;
1035 memset(&modeInfo, 0, sizeof(modeInfo));
1036 for (int i = 0;i < connector->count_modes; i++) {
1037 strncpy(modeInfo.name, drmModes[i].name, DRM_DISPLAY_MODE_LEN - 1);
1038 modeInfo.pixelW = drmModes[i].hdisplay;
1039 modeInfo.pixelH = drmModes[i].vdisplay;
1040 if (connector->mmWidth != 0 && connector->mmHeight != 0) {
1041 modeInfo.dpiX = (modeInfo.pixelW * 25.4f) / connector->mmWidth * 1000;
1042 modeInfo.dpiY = (modeInfo.pixelH * 25.4f) / connector->mmHeight * 1000;
1043 }
1044 modeInfo.refreshRate = drmModes[i].vrefresh;
1045 modeInfo.flags = drmModes[i].flags;
1046
1047 bool bNonFractionMode = false;
1048 if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) {
1049 // default add frac refresh rate config, like 23.976hz, 29.97hz...
1050 if (modeInfo.refreshRate == REFRESH_24kHZ
1051 || modeInfo.refreshRate == REFRESH_30kHZ
1052 || modeInfo.refreshRate == REFRESH_60kHZ
1053 || modeInfo.refreshRate == REFRESH_120kHZ
1054 || modeInfo.refreshRate == REFRESH_240kHZ) {
1055 if (mFracMode == MODE_ALL || mFracMode == MODE_FRACTION) {
1056 drm_mode_info_t fracMode = modeInfo;
1057 fracMode.refreshRate = (modeInfo.refreshRate * 1000) / (float)1001;
1058 fracMode.groupId = mConnecterModes.size();
1059 mConnecterModes.emplace(mConnecterModes.size(), fracMode);
1060 MESON_LOGD("add fraction display mode (%s)", fracMode.name);
1061 }
1062 } else {
1063 bNonFractionMode = true;
1064 }
1065 }
1066
1067 if (connector->connector_type != DRM_MODE_CONNECTOR_HDMIA ||
1068 mFracMode == MODE_ALL || mFracMode == MODE_NON_FRACTION) {
1069 bNonFractionMode = true;
1070 }
1071 // drm only send frame rate (int)59hz, its real frac refresh rate is 59.94hz
1072 if (modeInfo.refreshRate == 59.00) {
1073 modeInfo.refreshRate = (60 * 1000) / (float)1001;
1074 }
1075
1076 if (bNonFractionMode) {
1077 // add normal refresh rate config, like 24hz, 30hz...
1078 modeInfo.groupId = mConnecterModes.size();
1079 mConnecterModes.emplace(mConnecterModes.size(), modeInfo);
1080 }
1081 MESON_LOGD("add display mode (%s-%s, %dx%d, %f)",
1082 drmModes[i].name, modeInfo.name,
1083 modeInfo.pixelW, modeInfo.pixelH, modeInfo.refreshRate);
1084 }
1085 modes = mConnecterModes;
1086}
1087
1088int32_t ModePolicy::bindConnector(drmModeConnector *connector) {
1089 MESON_ASSERT(connector, "ModePolicy bindConnector get null connector!!");
1090
1091 MESON_LOGI("bindConnector: mConnector: %p\n", mConnector);
1092 std::map<uint32_t, drm_mode_info_t> modes;
1093 getModes(connector, modes);
1094
1095 mConnector = connector;
1096 switch (mConnector->connector_type) {
1097 case DRM_MODE_CONNECTOR_HDMIA:
1098 mDisplayType = DISPLAY_TYPE_MBOX;
1099 mConnectorType = CONN_TYPE_HDMI;
1100 mModeConType = MESON_MODE_HDMI;
1101 break;
1102 case LEGACY_NON_DRM_CONNECTOR_PANEL:
1103 case DRM_MODE_CONNECTOR_LVDS:
1104 case DRM_MODE_CONNECTOR_MESON_LVDS_A:
1105 case DRM_MODE_CONNECTOR_MESON_LVDS_B:
1106 case DRM_MODE_CONNECTOR_MESON_LVDS_C:
1107 case DRM_MODE_CONNECTOR_MESON_VBYONE_A:
1108 case DRM_MODE_CONNECTOR_MESON_VBYONE_B:
1109 case DRM_MODE_CONNECTOR_MESON_MIPI_A:
1110 case DRM_MODE_CONNECTOR_MESON_MIPI_B:
1111 case DRM_MODE_CONNECTOR_MESON_EDP_A:
1112 case DRM_MODE_CONNECTOR_MESON_EDP_B:
1113 mDisplayType = DISPLAY_TYPE_TV;
1114 mConnectorType = CONN_TYPE_PANEL;
1115 mModeConType = MESON_MODE_PANEL;
1116 break;
1117 case DRM_MODE_CONNECTOR_TV:
1118 mDisplayType = DISPLAY_TYPE_MBOX;
1119 mConnectorType = CONN_TYPE_CVBS;
1120 mModeConType = MESON_MODE_HDMI;
1121 break;
1122 default:
1123 MESON_LOGE("bindConnector unknown connector type:%d", mConnector->connector_type);
1124 mDisplayType = DISPLAY_TYPE_MBOX;
1125 mConnectorType = CONN_TYPE_HDMI;
1126 mModeConType = MESON_MODE_HDMI;
1127 break;
1128 }
1129 return 0;
1130}
1131
1132int32_t ModePolicy::bindCrtc(drmModeCrtcPtr crtc) {
1133 mCrtc = crtc;
1134 mAdapter->initDisplayAttributeInfo(mCrtc, mConnector);
1135 updateHdrCaps();
1136 return 0;
1137}
1138
1139/* *
1140 * @Description: init dv graphics priority when bootup.
1141 * */
1142void ModePolicy::initGraphicsPriority() {
1143 char mode[MESON_MODE_LEN] = {0};
1144 char defVal[MESON_MODE_LEN] = {"1"};
1145
1146 sys_get_string_prop_default(PROP_AMDV_PRIORITY, mode, defVal);
1147 setDisplayAttribute(DISPLAY_AMDV_GRAPHICS_PRIORITY, mode);
1148 sys_set_prop(PROP_AMDV_PRIORITY, mode);
1149}
1150
1151
1152/* *
1153 * @Description: set hdr mode
1154 * @params: mode "0":off "1":on "2":auto
1155 * */
1156void ModePolicy::setHdrMode(const char* mode) {
1157 if ((atoi(mode) >= 0) && (atoi(mode) <= 2)) {
1158 MESON_LOGI("setHdrMode state: %s\n", mode);
1159 setDisplayAttribute(DISPLAY_HDR_MODE, mode);
1160 sys_set_prop(PROP_HDR_MODE_STATE, mode);
1161 }
1162}
1163
1164/* *
1165 * @Description: set sdr mode
1166 * @params: mode "0":off "2":auto
1167 * */
1168void ModePolicy::setSdrMode(const char* mode) {
1169 if ((atoi(mode) == 0) || atoi(mode) == 2) {
1170 MESON_LOGI("setSdrMode state: %s\n", mode);
1171 setDisplayAttribute(DISPLAY_SDR_MODE, mode);
1172 sys_set_prop(PROP_SDR_MODE_STATE, mode);
1173 setBootEnv(UBOOTENV_SDR2HDR, (char *)mode);
1174 }
1175}
1176
1177
1178void ModePolicy::initHdrSdrMode() {
1179 char mode[MESON_MODE_LEN] = {0};
1180 char defVal[MESON_MODE_LEN] = {HDR_MODE_AUTO};
1181 sys_get_string_prop_default(PROP_HDR_MODE_STATE, mode, defVal);
1182 setHdrMode(mode);
1183 memset(mode, 0, sizeof(mode));
1184 bool flag = sys_get_bool_prop(PROP_ENABLE_SDR2HDR, false);
1185 if (flag & isDVEnable()) {
1186 strcpy(mode, SDR_MODE_OFF);
1187 } else {
1188 strcpy(defVal, flag ? SDR_MODE_AUTO : SDR_MODE_OFF);
1189 sys_get_string_prop_default(PROP_SDR_MODE_STATE, mode, defVal);
1190 }
1191 setSdrMode(mode);
1192}
1193
1194bool ModePolicy::checkDVStatusChanged(int state) {
1195 std::string curDvEnable = "";
1196 std::string curDvLLPolicy = "";
1197 int curDvMode = -1;
1198
1199 getDisplayAttribute(DISPLAY_AMDV_ENABLE, curDvEnable);
1200 getDisplayAttribute(DISPLAY_AMDV_LL_POLICY, curDvLLPolicy);
1201 MESON_LOGI("curDvEnable %s, curDvLLPolicy %s!!\n", curDvEnable.c_str(), curDvLLPolicy.c_str());
1202
1203 if (!strcmp(curDvEnable.c_str(), AMDV_DISABLE) ||
1204 !strcmp(curDvEnable.c_str(), "0"))
1205 curDvMode = AMDV_SET_DISABLE;
1206 else if (!strcmp(curDvLLPolicy.c_str(), "0"))
1207 curDvMode = AMDV_SET_ENABLE;
1208 else if (!strcmp(curDvLLPolicy.c_str(), "1"))
1209 curDvMode = AMDV_SET_ENABLE_LL_YUV;
1210 else if (!strcmp(curDvLLPolicy.c_str(), "2"))
1211 curDvMode = AMDV_SET_ENABLE_LL_RGB;
1212
1213 MESON_LOGI("curDvMode %d, want DvMode %d\n", curDvMode, state);
1214
1215 if (curDvMode != state) {
1216 return true;
1217 } else {
1218 return false;
1219 }
1220}
1221
1222//get edid crc value to check edid change
1223bool ModePolicy::isEdidChange() {
1224 char edid[MESON_MAX_STR_LEN] = {0};
1225 char crcvalue[MESON_MAX_STR_LEN] = {0};
1226 unsigned int crcheadlength = strlen(DEFAULT_EDID_CRCHEAD);
1227 sysfs_get_string(DISPLAY_EDID_VALUE, edid, MESON_MAX_STR_LEN);
1228 char *p = strstr(edid, DEFAULT_EDID_CRCHEAD);
1229 if (p != NULL && strlen(p) > crcheadlength) {
1230 p += crcheadlength;
1231 if (!getBootEnv(UBOOTENV_EDIDCRCVALUE, crcvalue) || strncmp(p, crcvalue, strlen(p))) {
1232 MESON_LOGI("update edidcrc: %s->%s\n", crcvalue, p);
1233 setBootEnv(UBOOTENV_EDIDCRCVALUE, p);
1234 return true;
1235 }
1236 }
1237 return false;
1238}
1239
1240void ModePolicy::saveDeepColorAttr(const char* mode, const char* dcValue) {
1241 char ubootvar[100] = {0};
1242 sprintf(ubootvar, "ubootenv.var.%s_deepcolor", mode);
1243 setBootEnv(ubootvar, (char *)dcValue);
1244}
1245
1246void ModePolicy::saveHdmiParamToEnv() {
1247 char outputMode[MESON_MODE_LEN] = {0};
1248 char dvenable[MESON_MODE_LEN] = {0};
1249
1250 getDisplayMode(outputMode);
1251 if (strlen(mDvInfo.amdv_enable) > 0)
1252 strcpy(dvenable, mDvInfo.amdv_enable);
1253
1254 // 1. check whether the TV changed or not, if changed save crc
1255 if (isEdidChange()) {
1256 MESON_LOGD("tv sink changed\n");
1257 }
1258
1259 // 2. save coloattr/hdmimode to bootenv if mode is not null or dummy_l
1260 if (strstr(outputMode, "cvbs") != NULL) {
1261 setBootEnv(UBOOTENV_CVBSMODE, (char *)outputMode);
1262 } else if (strcmp(outputMode, "null") && strcmp(outputMode, "dummy_l")) {
1263 std::string colorAttr;
1264 char colorDepth[MESON_MODE_LEN] = {0};
1265 char colorSpace[MESON_MODE_LEN] = {0};
1266 char dvstatus[MESON_MODE_LEN] = {0};
1267 char hdr_policy[MESON_MODE_LEN] = {0};
1268 // 2.1 save color attr
1269 getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, colorAttr);
1270 saveDeepColorAttr(outputMode, colorAttr.c_str());
1271 setBootEnv(UBOOTENV_COLORATTRIBUTE, colorAttr.c_str());
1272 //colorDepth&&colorSpace is used for uboot hdmi to find
1273 //best color attributes for the selected hdmi mode when TV changed
1274 char defVal[MESON_MODE_LEN] = {"8"};
1275 sys_get_string_prop_default(PROP_DEEPCOLOR_CTL, colorDepth, defVal);
1276 strcpy(defVal, "auto");
1277 sys_get_string_prop_default(PROP_PIXFMT, colorSpace, defVal);
1278 setBootEnv(UBOOTENV_HDMICOLORDEPTH, colorDepth);
1279 setBootEnv(UBOOTENV_HDMICOLORSPACE, colorSpace);
1280
limin.tian71ee0c22024-08-29 03:36:32 +00001281 // 2.2 save output mode,removed, we use hdmimode for hdmi.
leng.fang91856072024-06-07 14:12:54 +08001282 // 2.3 save dv status/dv_type
1283 // In follow sink mode: 0:disable 1:STD(or enable dv) 2:LL YUV 3: LL RGB
1284 // In follow source mode: dv is disable in uboot.
1285 if (isMboxSupportDV()) {
1286 char hdr_force_mode[MESON_MODE_LEN] = {0};
1287 memset(hdr_force_mode, 0, MESON_MODE_LEN);
1288 getBootEnv(UBOOTENV_HDR_FORCE_MODE, hdr_force_mode);
1289 getHdrStrategy(hdr_policy);
1290 if (!strcmp(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]) ||
1291 (!strcmp(hdr_policy, AMDV_POLICY_FORCE_MODE) && !strcmp(hdr_force_mode, FORCE_HDR10))) {
1292 sprintf(dvstatus, "%d", 0);
1293 } else {
leng.fangd8ab2872024-06-28 16:23:43 +08001294 sprintf(dvstatus, "%d", mSceneOutInfo.amdv_type);
leng.fang91856072024-06-07 14:12:54 +08001295 }
1296 setBootEnv(UBOOTENV_DOLBYSTATUS, dvstatus);
1297
1298 if (strlen(dvenable) > 0)
1299 setBootEnv(UBOOTENV_DV_ENABLE, dvenable);
1300
1301 MESON_LOGI("dvstatus %s dv_type %d dv_enable %s hdr_policy %s hdr_force_mode %s \n",
leng.fangd8ab2872024-06-28 16:23:43 +08001302 dvstatus, mSceneOutInfo.amdv_type, mDvInfo.amdv_enable, hdr_policy, hdr_force_mode);
leng.fang91856072024-06-07 14:12:54 +08001303
1304 } else {
1305 MESON_LOGI("MBOX is not support dv, dvstatus %s dv_type %d dv_enable %s\n",
leng.fangd8ab2872024-06-28 16:23:43 +08001306 dvstatus, mSceneOutInfo.amdv_type, mDvInfo.amdv_enable);
leng.fang91856072024-06-07 14:12:54 +08001307 }
1308
1309 MESON_LOGI("colorattr: %s, outputMode %s, cd %s, cs %s\n",
1310 colorAttr.c_str(), outputMode, colorDepth, colorSpace);
1311 }
1312}
1313
1314bool ModePolicy::updateEnv()
1315{
1316 if (mDisplayType == DISPLAY_TYPE_MBOX)
1317 saveHdmiParamToEnv();
1318 return true;
1319}
1320
1321void ModePolicy::enableDV(int DvMode) {
1322 if (isMboxSupportDV() == false) {
1323 MESON_LOGI("This platform is not support dv or has no dv ko");
1324 return;
1325 }
1326 MESON_LOGI("DvMode %d", DvMode);
1327
1328 strcpy(mDvInfo.amdv_enable, "1");
1329
1330 //if TV
1331 if (DISPLAY_TYPE_TV == mDisplayType) {
1332 setHdrMode(HDR_MODE_OFF);
1333 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FOLLOW_SINK);
1334 }
1335
1336 //if OTT
1337 char hdr_policy[MESON_MODE_LEN] = {0};
1338 getHdrStrategy(hdr_policy);
1339 if ((DISPLAY_TYPE_MBOX == mDisplayType) || (DISPLAY_TYPE_REPEATER == mDisplayType)) {
1340 switch (DvMode) {
1341 case AMDV_SET_ENABLE:
1342 MESON_LOGI("Dv set Mode [DV_RGB_444_8BIT]\n");
1343 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0");
1344 break;
1345 case AMDV_SET_ENABLE_LL_YUV:
1346 MESON_LOGI("Dv set Mode [LL_YCbCr_422_12BIT]\n");
1347 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0");
1348 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "1");
1349 break;
1350 case AMDV_SET_ENABLE_LL_RGB:
1351 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0");
1352 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "2");
1353 break;
1354 default:
1355 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0");
1356 }
1357
1358 if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) {
1359 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
1360 if (isDVEnable()) {
1361 setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
1362 }
1363 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) {
1364 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
1365 if (isDVEnable()) {
1366 setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
1367 }
1368 } else if (strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) {
1369 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]);
1370 if (isDVEnable()) {
1371 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE);
1372 }
1373 }
1374 }
1375
1376 setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_ENABLE);
1377 if (strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) {
1378 char hdr_force_mode[MESON_MODE_LEN] = {0};
1379 gethdrforcemode(hdr_force_mode);
1380 if (strstr(hdr_force_mode, FORCE_AMDV)) {
1381 setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_AMDV);
1382 } else if (strstr(hdr_force_mode, FORCE_HDR10)) {
1383 setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_HDR10);
1384 } else if (strstr(hdr_force_mode, AMDV_DISABLE_FORCE_SDR)) {
1385 // 8bit or not
1386 std::string cur_ColorAttribute;
1387 getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute);
1388 if (cur_ColorAttribute.find("8bit", 0) != std::string::npos) {
1389 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_8BIT);
1390 } else {
1391 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_10BIT);
1392 }
1393 }
1394 } else {
1395 int amdv_prop = DvMode == AMDV_SET_ENABLE_LL_YUV ? 1 : 0;
1396 setDisplayAttribute(DISPLAY_AMDV_MODE, to_string(amdv_prop));
1397 }
1398
1399 if (DISPLAY_TYPE_TV == mDisplayType) {
1400 setHdrMode(HDR_MODE_AUTO);
1401 }
1402
1403 initGraphicsPriority();
1404}
1405
1406void ModePolicy::disableDV(int DvMode) {
1407 //char tvmode[MESON_MODE_LEN] = {0};
1408 int check_status_count = 0;
1409 [[maybe_unused]] int amdv_type = DvMode;
1410
1411 MESON_LOGI("amdv_type %d", amdv_type);
1412 strcpy(mDvInfo.amdv_enable, "0");
1413
1414 //2. update sysfs
1415 char hdr_policy[MESON_MODE_LEN] = {0};
1416 getHdrStrategy(hdr_policy);
1417
1418 if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) {
1419 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
1420 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) {
1421 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
1422 }
1423
1424 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE);
1425 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_MODE_BYPASS);
1426 usleep(100000);//100ms
1427 std::string dvstatus = "";
1428 getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus);
1429
1430 if (strcmp(dvstatus.c_str(), BYPASS_PROCESS)) {
1431 while (++check_status_count <30) {
1432 usleep(20000);//20ms
1433 getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus);
1434 if (!strcmp(dvstatus.c_str(), BYPASS_PROCESS)) {
1435 break;
1436 }
1437 }
1438 }
1439
1440 MESON_LOGI("dvstatus %s, check_status_count [%d]", dvstatus.c_str(), check_status_count);
1441 setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_DISABLE);
1442
1443 if (DISPLAY_TYPE_TV == mDisplayType) {
1444 setHdrMode(HDR_MODE_AUTO);
1445 }
1446
1447 setSdrMode(SDR_MODE_AUTO);
1448}
1449
1450void ModePolicy::getPosition(const char* curMode, int *position) {
1451 char keyValue[20] = {0};
1452 char ubootvar[100] = {0};
1453 int defaultWidth = 0;
1454 int defaultHeight = 0;
1455 std::map<uint32_t, drm_mode_info_t> connecterModeList;
1456
1457 drm_mode_info_t mode = {
1458 "null",
1459 0, 0,
1460 0, 0,
1461 60.0,
1462 0
1463 };
1464
1465 if (mConnector->connection == DRM_MODE_CONNECTED) {
1466 getModes(mConnector, connecterModeList);
1467
1468 for (auto it = connecterModeList.begin(); it != connecterModeList.end(); it++) {
1469 if (mConnector->connector_type == DRM_MODE_CONNECTOR_TV) {
1470 if (strstr(curMode, it->second.name)) {
1471 strcpy(keyValue, curMode);
1472 mode = it->second;
1473 break;
1474 }
1475 } else {
1476 if (strstr(curMode, it->second.name)) {
1477 if (strstr(it->second.name, MODE_4K2KSMPTE_PREFIX)) {
1478 strcpy(keyValue, "4k2ksmpte");
1479 } else if (strstr(it->second.name, MODE_PANEL)) {
1480 strcpy(keyValue, MODE_PANEL);
1481 } else if (strchr(curMode,'p')) {
1482 strncpy(keyValue, curMode, strchr(curMode,'p') - curMode + 1);
1483 } else if (strchr(curMode,'i')){
1484 strncpy(keyValue, curMode, strchr(curMode,'i') - curMode + 1);
1485 }
1486 mode = it->second;
1487 break;
1488 }
1489 }
1490 }
1491 }
1492
1493 if (keyValue[0] != '0') {
1494 defaultWidth = mode.pixelW;
1495 defaultHeight = mode.pixelH;
1496 } else {
1497 strcpy(keyValue, MODE_1080P_PREFIX);
1498 defaultWidth = FULL_WIDTH_1080;
1499 defaultHeight = FULL_HEIGHT_1080;
1500 }
1501
1502 pthread_mutex_lock(&mEnvLock);
1503 sprintf(ubootvar, "ubootenv.var.%s_x", keyValue);
1504 position[0] = getBootenvInt(ubootvar, 0);
1505 sprintf(ubootvar, "ubootenv.var.%s_y", keyValue);
1506 position[1] = getBootenvInt(ubootvar, 0);
1507 sprintf(ubootvar, "ubootenv.var.%s_w", keyValue);
1508 position[2] = getBootenvInt(ubootvar, defaultWidth);
1509 sprintf(ubootvar, "ubootenv.var.%s_h", keyValue);
1510 position[3] = getBootenvInt(ubootvar, defaultHeight);
1511
1512 MESON_LOGI("%s curMode:%s position[0]:%d position[1]:%d position[2]:%d position[3]:%d\n", __FUNCTION__, curMode, position[0], position[1], position[2], position[3]);
1513
1514 pthread_mutex_unlock(&mEnvLock);
1515
1516}
1517
1518void ModePolicy::setPosition(const char* curMode, int left, int top, int width, int height) {
1519 char x[512] = {0};
1520 char y[512] = {0};
1521 char w[512] = {0};
1522 char h[512] = {0};
1523 sprintf(x, "%d", left);
1524 sprintf(y, "%d", top);
1525 sprintf(w, "%d", width);
1526 sprintf(h, "%d", height);
1527
1528 MESON_LOGI("%s curMode:%s left:%d top:%d width:%d height:%d\n", __FUNCTION__, curMode, left, top, width, height);
1529
1530 char keyValue[20] = {0};
1531 char ubootvar[100] = {0};
1532 bool find = false;
1533 std::map<uint32_t, drm_mode_info_t> connecterModeList;
1534
1535 if (mConnector->connection == DRM_MODE_CONNECTED) {
1536 getModes(mConnector, connecterModeList);
1537
1538 for (auto it = connecterModeList.begin(); it != connecterModeList.end(); it++) {
1539 if (mConnector->connector_type == DRM_MODE_CONNECTOR_TV) {
1540 if (strstr(curMode, it->second.name)) {
1541 strcpy(keyValue, curMode);
1542 find = true;
1543 break;
1544 }
1545 } else {
1546 if (strstr(curMode, it->second.name)) {
1547 if (strstr(it->second.name, MODE_4K2KSMPTE_PREFIX)) {
1548 strcpy(keyValue, "4k2ksmpte");
1549 find = true;
1550 } else if (strstr(it->second.name, MODE_PANEL)) {
1551 strcpy(keyValue, MODE_PANEL);
1552 find = true;
1553 } else if (strchr(curMode,'p')) {
1554 strncpy(keyValue, curMode, strchr(curMode,'p') - curMode + 1);
1555 find = true;
1556 } else if (strchr(curMode,'i')){
1557 strncpy(keyValue, curMode, strchr(curMode,'i') - curMode + 1);
1558 find = true;
1559 }
1560 break;
1561 }
1562 }
1563 }
1564 }
1565
1566 if (!find)
1567 return;
1568
1569 mAdapter->setDisplayRect(left, top, width , height);
1570}
1571
1572void ModePolicy::setDigitalMode(const char* mode) {
1573 if (mode == NULL) return;
1574
1575 if (!strcmp("PCM", mode)) {
1576 sysfs_set_string(AUDIO_DSP_DIGITAL_RAW, "0");
1577 sysfs_set_string(AV_HDMI_CONFIG, "audio_on");
1578 } else if (!strcmp("SPDIF passthrough", mode)) {
1579 sysfs_set_string(AUDIO_DSP_DIGITAL_RAW, "1");
1580 sysfs_set_string(AV_HDMI_CONFIG, "audio_on");
1581 } else if (!strcmp("HDMI passthrough", mode)) {
1582 sysfs_set_string(AUDIO_DSP_DIGITAL_RAW, "2");
1583 sysfs_set_string(AV_HDMI_CONFIG, "audio_on");
1584 }
1585}
1586
1587bool ModePolicy::getDisplayMode(char* mode) {
1588 bool ret = false;
1589
1590 if (mode != NULL) {
1591 ret = mAdapter->getDisplayMode(mode);
1592 MESON_LOGI("%s mode:%s\n", __FUNCTION__, mode);
1593 } else {
1594 MESON_LOGE("%s mode is NULL\n", __FUNCTION__);
1595 }
1596
1597 return ret;
1598}
1599
1600//set hdmi output mode
1601int32_t ModePolicy::setDisplayMode(std::string &mode) {
1602 MESON_LOGI("%s mode:%s\n", __FUNCTION__, mode.c_str());
1603 mAdapter->setDisplayMode(mode);
1604 return 0;
1605}
1606
1607int32_t ModePolicy::setDisplayMode(const char *mode) {
1608 if (!mode) {
1609 MESON_LOGE("ModePolicy::setDisplayMode null mode");
1610 return -EINVAL;
1611 }
1612 std::string displayMode(mode);
1613 return setDisplayMode(displayMode);
1614}
1615
1616bool ModePolicy::setDisplayAttribute(const std::string cmd, const std::string attribute) {
1617 return mAdapter->setDisplayAttribute(cmd, attribute);
1618}
1619bool ModePolicy::getDisplayAttribute(const std::string cmd, std::string& attribute) {
1620 return mAdapter->getDisplayAttribute(cmd, attribute);
1621}
1622
1623bool ModePolicy::isMatchMode(char* curmode, const char* outputmode) {
1624 bool ret = false;
1625 char tmpMode[MESON_MODE_LEN] = {0};
1626
1627 char *pCmp = curmode;
1628 //check line feed key
1629 char *pos = strchr(pCmp, 0x0a);
1630 if (NULL == pos) {
1631 //check return key
1632 char *pos = strchr(pCmp, 0x0d);
1633 if (NULL == pos) {
1634 strcpy(tmpMode, pCmp);
1635 } else {
1636 strncpy(tmpMode, pCmp, pos - pCmp);
1637 }
1638 } else {
1639 strncpy(tmpMode, pCmp, pos - pCmp);
1640 }
1641
1642 MESON_LOGI("curmode:%s, tmpMode:%s, outputmode:%s\n", curmode, tmpMode, outputmode);
1643
1644 if (!strcmp(tmpMode, outputmode)) {
1645 ret = true;
1646 }
1647
1648 return ret;
1649}
1650
1651bool ModePolicy::isTvSupportALLM() {
1652 char allm_mode_cap[PROP_VALUE_MAX];
1653 memset(allm_mode_cap, 0, PROP_VALUE_MAX);
1654 int ret = 0;
1655
1656 sysfs_get_string(AUTO_LOW_LATENCY_MODE_CAP, allm_mode_cap, PROP_VALUE_MAX);
1657
1658 for (int i = 0; i < ARRAY_SIZE(ALLM_MODE_CAP); i++) {
1659 if (!strncmp(allm_mode_cap, ALLM_MODE_CAP[i], strlen(ALLM_MODE_CAP[i]))) {
1660 ret = i;
1661 }
1662 }
1663
1664 return (ret == 1) ? true : false;
1665}
1666
1667bool ModePolicy::getContentTypeSupport(const char* type) {
1668 char content_type_cap[MESON_MAX_STR_LEN] = {0};
1669 sysfs_get_string(HDMI_CONTENT_TYPE_CAP, content_type_cap, MESON_MAX_STR_LEN);
1670 if (strstr(content_type_cap, type)) {
1671 MESON_LOGI("getContentTypeSupport: %s is true", type);
1672 return true;
1673 }
1674
1675 MESON_LOGI("getContentTypeSupport: %s is false", type);
1676 return false;
1677}
1678
1679bool ModePolicy::getGameContentTypeSupport() {
1680 return getContentTypeSupport(CONTENT_TYPE_CAP[3]);
1681}
1682
1683bool ModePolicy::getSupportALLMContentTypeList(std::vector<std::string> *supportModes) {
1684 if (isTvSupportALLM()) {
1685 (*supportModes).push_back(std::string("allm"));
1686 }
1687
1688 for (int i = 0; i < ARRAY_SIZE(CONTENT_TYPE_CAP); i++) {
1689 if (getContentTypeSupport(CONTENT_TYPE_CAP[i])) {
1690 (*supportModes).push_back(std::string(CONTENT_TYPE_CAP[i]));
1691 }
1692 }
1693
1694 return true;
1695}
1696
1697
1698void ModePolicy::setTvDVEnable() {
1699 //if TV
1700 setHdrMode(HDR_MODE_OFF);
1701 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FOLLOW_SINK);
1702
1703 usleep(100000);//100ms
1704 setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_ENABLE);
1705 usleep(100000);//100ms
1706
1707 setHdrMode(HDR_MODE_AUTO);
1708
1709 initGraphicsPriority();
1710}
1711
1712void ModePolicy::setTvDVDisable() {
1713 int check_status_count = 0;
1714
1715 //2. update sysfs
1716 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
1717
1718 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE);
1719 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_MODE_BYPASS);
1720 usleep(100000);//100ms
1721 std::string dvstatus = "";
1722 getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus);
1723
1724 if (strcmp(dvstatus.c_str(), BYPASS_PROCESS)) {
1725 while (++check_status_count <30) {
1726 usleep(20000);//20ms
1727 getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus);
1728 if (!strcmp(dvstatus.c_str(), BYPASS_PROCESS)) {
1729 break;
1730 }
1731 }
1732 }
1733
1734 MESON_LOGI("dvstatus %s, check_status_count [%d]", dvstatus.c_str(), check_status_count);
1735 setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_DISABLE);
1736
1737 setHdrMode(HDR_MODE_AUTO);
1738 setSdrMode(SDR_MODE_AUTO);
1739}
1740
1741
1742int32_t ModePolicy::setDvMode(std::string &amdv_mode) {
1743 MESON_LOGI("%s dv mode:%s", __FUNCTION__, amdv_mode.c_str());
1744
1745 if (DISPLAY_TYPE_TV == mDisplayType) {
1746 //1. update prop
1747 strcpy(mConData.hdr_info.ubootenv_dv_type, amdv_mode.c_str());
1748
1749 //2. apply to driver
1750 if (strstr(amdv_mode.c_str(), "0")) {
1751 strcpy(mDvInfo.amdv_enable, "0");
1752 setTvDVDisable();
1753 } else {
1754 strcpy(mDvInfo.amdv_enable, "1");
1755 setTvDVEnable();
1756 }
1757
1758 //3. save env
1759 setBootEnv(UBOOTENV_DV_ENABLE, mDvInfo.amdv_enable);
1760 } else {
1761 //1. update dv env
1762 strcpy(mConData.hdr_info.ubootenv_dv_type, amdv_mode.c_str());
1763
1764 if (strstr(amdv_mode.c_str(), "0")) {
1765 strcpy(mDvInfo.amdv_enable, "0");
1766 } else {
1767 strcpy(mDvInfo.amdv_enable, "1");
1768 }
1769
1770 //Save user prefer dv mode only user change dv through UI
1771 setBootEnv(UBOOTENV_USER_DV_TYPE, mConData.hdr_info.ubootenv_dv_type);
1772 setBootEnv(UBOOTENV_DV_ENABLE, mDvInfo.amdv_enable);
1773 setBootEnv(UBOOTENV_DOLBYSTATUS, amdv_mode.c_str());
1774
1775 //2. set hdmi mode for trigger setting
1776 setSourceOutputMode(mCurrentMode);
1777 }
1778
1779 return 0;
1780}
1781
1782
1783/* *
1784 * @Description: this is a temporary solution, should be revert when android.hardware.graphics.composer@2.4 finished
1785 * set the ALLM_Mode
1786 * @params: "0": ALLM disable (VSIF still contain allm info)
1787 * "1": ALLM enable
1788 * "-1":really disable ALLM (VSIF don't contain allm info)
1789 * */
1790void ModePolicy::setALLMMode(int state) {
1791 /***************************************************************
1792 * Comment for special solution in this func *
1793 ***************************************************************
1794 * *
1795 * In HDMI Standard only 0 to disable ALLM and 1 to enable ALLM*
1796 * but ALLM and DV share the same bit in VSIF *
1797 * it cause conflict *
1798 * *
1799 * So in amlogic special solution: *
1800 * we add -1 to *
1801 * 1: disable ALLM *
1802 * 2: clean ALLM info in VSIF conflict bit *
1803 * when user set 0 to ALLM *
1804 * we will force change 0 into -1 here *
1805 * *
1806 ***************************************************************/
1807
1808 if (!isTvSupportALLM()) {
1809 SYS_LOGI("setALLMMode: TV not support ALLM\n");
1810 return;
1811 }
1812
1813 int perState = -1;
1814 char cur_allm_state[MESON_MODE_LEN] = {0};
1815 sysfs_get_string(AUTO_LOW_LATENCY_MODE, cur_allm_state, MESON_MODE_LEN);
1816 perState = atoi(cur_allm_state);
1817 if (perState == state) {
1818 SYS_LOGI("setALLMMode: the ALLM_Mode is not changed :%d\n", state);
1819 return;
1820 }
1821
1822 bool isTVSupportDV = isTvSupportDV();
1823
1824 char ubootenv_amdv_enable[MESON_MODE_LEN] = {0};
1825 std::string cur_ColorAttribute;
1826 char ubootenv_amdv_type[MESON_MODE_LEN] = {0};
1827 bool ret = false;
1828
1829 switch (state) {
1830 case -1:
1831 [[fallthrough]];
1832 case 0:
1833 //1. disable allm
1834 sysfs_set_string(AUTO_LOW_LATENCY_MODE, ALLM_MODE[0]);
1835 MESON_LOGI("setALLMMode: ALLM_Mode: %s", ALLM_MODE[0]);
1836 //2.1 get dv status before enable allm
1837 getBootEnv(UBOOTENV_DV_ENABLE, ubootenv_amdv_enable);
1838 //2.2 get current hdmi output resolution
1839 getDisplayMode(mCurrentMode);
1840 //2.3 get current hdmi output color space
1841 getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute);
1842 //2.4 get dv type before enable allm
1843 ret = getBootEnv(UBOOTENV_USER_DV_TYPE, ubootenv_amdv_type);
1844 //3 enable dv
1845 //when TV and current resolution support dv and dv is enable before enable allm
1846 if (isTVSupportDV
1847 && !strcmp(ubootenv_amdv_enable, "1")
1848 && !(meson_mode_support_mode(mModeConType, MESON_DOLBY_VISION_PRIORITY, mCurrentMode))) {
1849 // restore doblyvision when set -1/0 to ALLM
1850 if (!ret) {
1851 //best dv policy:sink-led -->source led
1852 if (strstr(mConData.hdr_info.dv_deepcolor, "DV_RGB_444_8BIT") != NULL
1853 && strstr(cur_ColorAttribute.c_str(), "444,8bit") != NULL) {
1854 enableDV(AMDV_SET_ENABLE);
leng.fangd8ab2872024-06-28 16:23:43 +08001855 mSceneOutInfo.amdv_type = AMDV_SET_ENABLE;
leng.fang91856072024-06-07 14:12:54 +08001856 } else if (strstr(mConData.hdr_info.dv_deepcolor, "LL_YCbCr_422_12BIT") != NULL
1857 && strstr(cur_ColorAttribute.c_str(), "422,12bit") != NULL) {
1858 enableDV(AMDV_SET_ENABLE_LL_YUV);
leng.fangd8ab2872024-06-28 16:23:43 +08001859 mSceneOutInfo.amdv_type = AMDV_SET_ENABLE_LL_YUV;
leng.fang91856072024-06-07 14:12:54 +08001860 } else {
1861 SYS_LOGI("can't enable dv for dv_deepcolor: %s and curColorAttribute: %s\n",
1862 mConData.hdr_info.dv_deepcolor, cur_ColorAttribute.c_str());
1863 }
1864 } else if (!strcmp(ubootenv_amdv_type, "2") && strstr(cur_ColorAttribute.c_str(), "422,12bit") != NULL) {
1865 enableDV(AMDV_SET_ENABLE_LL_YUV);
leng.fangd8ab2872024-06-28 16:23:43 +08001866 mSceneOutInfo.amdv_type = AMDV_SET_ENABLE_LL_YUV;
leng.fang91856072024-06-07 14:12:54 +08001867 } else if (!strcmp(ubootenv_amdv_type, "1") && strstr(cur_ColorAttribute.c_str(), "444,8bit") != NULL) {
1868 enableDV(AMDV_SET_ENABLE);
leng.fangd8ab2872024-06-28 16:23:43 +08001869 mSceneOutInfo.amdv_type = AMDV_SET_ENABLE;
leng.fang91856072024-06-07 14:12:54 +08001870 } else {
1871 SYS_LOGI("can't enable dv for curColorAttribute: %s\n", cur_ColorAttribute.c_str());
1872 }
1873 }
1874 break;
1875 case 1:
1876 //when TV support dv and dv is enable
1877 if (isTVSupportDV && isDVEnable()) {
leng.fangd8ab2872024-06-28 16:23:43 +08001878 mSceneOutInfo.amdv_type = AMDV_SET_DISABLE;
leng.fang91856072024-06-07 14:12:54 +08001879 // disable the doblyvision when ALLM enable
1880 disableDV(AMDV_SET_DISABLE);
1881 }
1882 //2. enable allm
1883 sysfs_set_string(AUTO_LOW_LATENCY_MODE, ALLM_MODE[2]);
1884 MESON_LOGI("setALLMMode: ALLM_Mode: %s", ALLM_MODE[2]);
1885 break;
1886 default:
1887 MESON_LOGE("setALLMMode: ALLM_Mode: error state[%d]", state);
1888 break;
1889 }
1890}
1891
1892bool ModePolicy::isTvConnector() {
1893 auto type = mConnector->connector_type;
1894 if (type == DRM_MODE_CONNECTOR_MESON_LVDS_A || type == DRM_MODE_CONNECTOR_MESON_LVDS_B ||
1895 type == DRM_MODE_CONNECTOR_MESON_LVDS_C || type == DRM_MODE_CONNECTOR_MESON_VBYONE_A ||
1896 type == DRM_MODE_CONNECTOR_MESON_VBYONE_B || type == DRM_MODE_CONNECTOR_LVDS ||
1897 type == LEGACY_NON_DRM_CONNECTOR_PANEL)
1898 return true;
1899
1900 return false;
1901}
1902
1903int32_t ModePolicy::setAutoLowLatencyMode(bool enabled) {
1904 auto type = mConnector->connector_type;
1905 if (type == DRM_MODE_CONNECTOR_HDMIA) {
1906 if (!isTvSupportALLM()) {
1907 return -1;
1908 }
1909
1910 if (enabled) {
1911 sysfs_set_string(LOW_LATENCY, LOW_LATENCY_ENABLE);
1912 } else {
1913 sysfs_set_string(LOW_LATENCY, LOW_LATENCY_DISABLE);
1914 }
1915 setALLMMode(enabled);
1916 return 0;
1917 }
1918
1919 // do nothing for tv
1920 if (isTvConnector())
1921 return 0;
1922
1923 return -1;
1924}
1925
1926void ModePolicy::setAllowedHdrTypes(uint32_t allowedHdrTypes, bool isAuto, bool passThrough) {
1927 //Match content Dynamic range
1928 if (passThrough) {
1929 setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_MATCH_CONTENT]);
1930 }
1931 // force SDR when autoAllowedHdrTypes are empty on system-preferred conversion
1932 else if (allowedHdrTypes == 0 && isAuto) {
1933 uint32_t userHdrType = 0;
1934 userHdrType = userHdrType | (1 << HAL_HDR_AMDV);
1935 userHdrType = userHdrType | (1 << HAL_HDR_HDR10);
1936 userHdrType = userHdrType | (1 << HAL_HDR_HLG);
1937 userHdrType = userHdrType | (1 << DRM_INVALID);
1938 string keyValue = std::to_string(userHdrType);
1939 setBootEnv(UBOOTENV_USER_PREFERRED_HDR_TYPE, keyValue.c_str());
1940 setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_SYSTEM_PREFERRED]);
1941 return;
1942 } else {
1943 //bit0-bit4 for hdr type and 1 is disable 0 is enable
1944 uint32_t userHdrType = 0;
1945 userHdrType = userHdrType | (1 << HAL_HDR_AMDV);
1946 userHdrType = userHdrType | (1 << HAL_HDR_HDR10);
1947 userHdrType = userHdrType | (1 << HAL_HDR_HLG);
1948 userHdrType = userHdrType | (1 << DRM_INVALID);
1949 allowedHdrTypes ^= userHdrType;
1950 allowedHdrTypes &= userHdrType;
1951 string keyValue = std::to_string(allowedHdrTypes);
1952 setBootEnv(UBOOTENV_USER_PREFERRED_HDR_TYPE, keyValue.c_str());
1953 if (isAuto)
1954 setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_SYSTEM_PREFERRED]);
1955 else
1956 setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_FORCE]);
1957
1958 MESON_LOGD("%s AllowedHdrType %d isAuto %d keyValue %s \n", __func__, allowedHdrTypes, isAuto, keyValue.c_str());
1959 }
1960
1961 return;
1962}
1963
1964int32_t ModePolicy::getPreferredHdrConversionType(void) {
1965 int32_t outHdrConversionType = -1;
1966
1967 char auto_policy[MESON_MODE_LEN] = {0};
1968 memset(auto_policy, 0, MESON_MODE_LEN);
1969 getBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, auto_policy);
1970
1971 //Match content Dynamic range
1972 if (strstr(auto_policy, MESON_HDR_PREFERRED_POLICY[MESON_HDR_MATCH_CONTENT])) {
1973 mHdr_policy = MESON_HDR_POLICY_SOURCE;
1974 mHdr_priority = MESON_G_DV_HDR10_HLG;
1975 }
1976 //System-preferred conversion or Force conversion
1977 else {
1978 bool isAuto = true;
1979 if (strstr(auto_policy, MESON_HDR_PREFERRED_POLICY[MESON_HDR_FORCE])) {
1980 isAuto = false;
1981 }
1982
1983 char user_hdr_type[MESON_MODE_LEN] = {0};
1984 memset(user_hdr_type, 0, MESON_MODE_LEN);
1985 bool ret = getBootEnv(UBOOTENV_USER_PREFERRED_HDR_TYPE, user_hdr_type);
1986 int32_t allowedHdrType = atoi(user_hdr_type);
1987 if (ret) {
1988 allowedHdrType = atoi(user_hdr_type);
1989 } else {
1990 allowedHdrType = 0; //all hdr enable as default
1991 }
1992
1993 //force SDR when autoAllowedHdrTypes are empty on system-preferred conversion
1994 uint32_t userHdrType = 0;
1995 userHdrType = userHdrType | (1 << HAL_HDR_AMDV);
1996 userHdrType = userHdrType | (1 << HAL_HDR_HDR10);
1997 userHdrType = userHdrType | (1 << HAL_HDR_HLG);
1998 userHdrType = userHdrType | (1 << DRM_INVALID);
1999 string keyValue = std::to_string(userHdrType);
2000 if (isAuto && strstr (user_hdr_type, keyValue.c_str())) {
2001 mHdr_priority = MESON_G_SDR;
2002 outHdrConversionType = DRM_INVALID;
2003 } else {
2004 bool containDVType = false, containHDR10Type = false,
2005 containHLGType = false, containSDRType = false;
2006
2007 MESON_LOGD("allowedHdrType 0x%x ", allowedHdrType);
2008 if (!(allowedHdrType & (1 << HAL_HDR_AMDV)))
2009 containDVType = true;
2010 if (!(allowedHdrType & (1 << HAL_HDR_HDR10)))
2011 containHDR10Type = true;
2012 if (!(allowedHdrType & (1 << HAL_HDR_HLG)))
2013 containHLGType = true;
2014 if (!(allowedHdrType & (1 << DRM_INVALID)))
2015 containSDRType = true;
2016
2017 drm_hdr_capabilities hdrCaps;
2018 getHdrCapabilities(&hdrCaps);
2019
2020 if (isAuto) {
2021 if (hdrCaps.DVSupported) {
2022 if (containHLGType && containHDR10Type && containDVType) {
2023 mHdr_policy = MESON_HDR_POLICY_SINK;
2024 mHdr_priority = MESON_G_DV_HDR10_HLG;
2025 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2026 } else if (containHDR10Type && containDVType) {
2027 mHdr_policy = MESON_HDR_POLICY_SINK;
2028 mHdr_priority = MESON_G_DV_HDR10;
2029 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2030 } else if (containHLGType && containDVType) {
2031 mHdr_policy = MESON_HDR_POLICY_SINK;
2032 mHdr_priority = MESON_G_DV_HLG;
2033 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2034 } else if (containHLGType && containHDR10Type) {
2035 mHdr_policy = MESON_HDR_POLICY_SINK;
2036 mHdr_priority = MESON_G_HDR10_HLG;
2037 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10);
2038 } else if (containDVType) {
2039 mHdr_policy = MESON_HDR_POLICY_SINK;
2040 mHdr_priority = MESON_G_DV;
2041 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2042 } else if (containHDR10Type) {
2043 mHdr_policy = MESON_HDR_POLICY_SINK;
2044 mHdr_priority = MESON_G_HDR10;
2045 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10);
2046 } else if (containHLGType) {
2047 mHdr_priority = MESON_G_HLG;
2048 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source due to dv can't HLG output
2049 } else {
2050 mHdr_policy = MESON_HDR_POLICY_SINK;
2051 mHdr_priority = MESON_G_SDR;
2052 outHdrConversionType = DRM_INVALID; //force sdr
2053 }
2054 } else {
2055 if (containHLGType && containHDR10Type) {
2056 mHdr_policy = MESON_HDR_POLICY_SINK;
2057 mHdr_priority = MESON_G_HDR10_HLG;
2058 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10);
2059 } else if (containHDR10Type) {
2060 mHdr_policy = MESON_HDR_POLICY_SINK;
2061 mHdr_priority = MESON_G_HDR10;
2062 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10);
2063 } else if (containHLGType) {
2064 mHdr_policy = MESON_HDR_POLICY_SINK;
2065 mHdr_priority = MESON_G_HLG;
2066 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HLG);
2067 } else {
2068 mHdr_policy = MESON_HDR_POLICY_SINK;
2069 mHdr_priority = MESON_G_SDR;
2070 outHdrConversionType = DRM_INVALID; //force sdr
2071 }
2072 }
2073 } else {
2074 if (containDVType) {
2075 if (hdrCaps.DVSupported) {
2076 mHdr_policy = MESON_HDR_POLICY_SINK;
2077 mHdr_priority = MESON_G_DV;
2078 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2079 } else {
2080 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source
2081 mHdr_priority = MESON_G_DV_HDR10_HLG;
2082 }
2083 } else if (containHDR10Type) {
2084 if (hdrCaps.HDR10Supported) {
2085 mHdr_policy = MESON_HDR_POLICY_SINK;
2086 mHdr_priority = MESON_G_HDR10;
2087 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10);
2088 } else {
2089 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source
2090 mHdr_priority = MESON_G_DV_HDR10_HLG;
2091 }
2092 } else if (containHLGType) {
2093 if (hdrCaps.HLGSupported) {
2094 if (hdrCaps.DVSupported) {
2095 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source due to dv can't HLG output
2096 mHdr_priority = MESON_G_DV_HDR10_HLG;
2097 } else {
2098 mHdr_policy = MESON_HDR_POLICY_SINK;
2099 mHdr_priority = MESON_G_HLG;
2100 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HLG);
2101 }
2102 } else {
2103 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source
2104 mHdr_priority = MESON_G_DV_HDR10_HLG;
2105 }
2106 } else {
2107 mHdr_policy = MESON_HDR_POLICY_SINK;
2108 mHdr_priority = MESON_G_SDR;
2109 outHdrConversionType = DRM_INVALID; //force sdr
2110 }
2111 }
2112 }
2113 }
2114
2115 MESON_LOGD("hdr_policy:%d hdr_priority:0x%x outHdrConversionType:%d ", mHdr_policy, mHdr_priority, outHdrConversionType);
2116 return outHdrConversionType;
2117}
2118
2119int32_t ModePolicy::setHdrConversionPolicy(bool passthrough, int32_t forceType) {
2120 int32_t ret = 0;
2121 MESON_LOGD("%s passthrough %d forceType %d",
2122 __func__, passthrough, forceType);
2123
2124 if (passthrough || (forceType == -1)) {
2125 setBootEnv(UBOOTENV_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
2126
2127 char hdr_priority[MESON_MODE_LEN] = {0};
2128 sprintf(hdr_priority, "%d", mHdr_priority);
2129 setBootEnv(UBOOTENV_HDR_PRIORITY, hdr_priority);
2130 // set current hdmi mode
2131 getDisplayMode(mCurrentMode);
2132 setSourceOutputMode(mCurrentMode);
2133 } else {
2134 std::string type = FORCE_AMDV;
2135 meson_hdr_priority_e priority = MESON_DOLBY_VISION_PRIORITY;
2136 switch (forceType) {
2137 case DRM_AMDV: {
2138 priority = MESON_DOLBY_VISION_PRIORITY;
2139 type = FORCE_AMDV;
2140 break;
2141 }
2142 case DRM_HDR10:{
2143 priority = MESON_HDR10_PRIORITY;
2144 type = FORCE_HDR10;
2145 break;
2146 }
2147 case DRM_HLG:{
2148 priority = MESON_HDR10_PRIORITY;
2149 type = FORCE_HLG;
2150 break;
2151 }
2152 case DRM_INVALID: {
2153 priority = MESON_SDR_PRIORITY;
2154 type = AMDV_DISABLE_FORCE_SDR;
2155 break;
2156 }
2157 default:
2158 MESON_LOGE("setHdrConversionStrategy: error type[%d]", forceType);
2159 ret = -1;
2160 break;
2161 }
2162
2163 if (!ret) {
2164 getDisplayMode(mCurrentMode);
2165 meson_mode_set_policy_input(mModeConType, &mConData);
2166 if (!meson_mode_support_mode(mModeConType, priority, mCurrentMode)) {
2167 char hdr_policy[MESON_MODE_LEN] = {0};
2168 sprintf(hdr_policy, "%d", mHdr_policy);
2169 setBootEnv(UBOOTENV_HDR_POLICY, hdr_policy);
2170
2171 char hdr_priority[MESON_MODE_LEN] = {0};
2172 sprintf(hdr_priority, "%d", mHdr_priority);
2173 setBootEnv(UBOOTENV_HDR_PRIORITY, hdr_priority);
2174
2175 setSourceOutputMode(mCurrentMode);
2176 } else {
2177 MESON_LOGW("%s mode check failed\n", __func__);
2178 ret = -EINVAL;
2179 }
2180 }
2181 }
2182
2183 return ret;
2184}
2185
2186/*
2187* apply setting
2188*/
2189void ModePolicy::applyDisplaySetting(bool force) {
2190 //quiescent boot need not output
2191 bool quiescent = sys_get_bool_prop("ro_boot_quiescent", false);
2192
2193 MESON_LOGI("quiescent_mode is %d\n", quiescent);
2194 if (quiescent && (mState == OUTPUT_MODE_STATE_INIT)) {
2195 MESON_LOGI("don't need to setting hdmi when quiescent mode\n");
2196 return;
2197 }
2198
2199 //check cvbs mode
2200 bool cvbsMode = false;
2201
2202 if (!strcmp(mSceneOutInfo.displaymode, MODE_480CVBS) || !strcmp(mSceneOutInfo.displaymode, MODE_576CVBS)
2203 || !strcmp(mSceneOutInfo.displaymode, MODE_PAL_M) || !strcmp(mSceneOutInfo.displaymode, MODE_PAL_N)
2204 || !strcmp(mSceneOutInfo.displaymode, MODE_NTSC_M)
2205 || !strcmp(mSceneOutInfo.displaymode, "null") || !strcmp(mSceneOutInfo.displaymode, "dummy_l")
2206 || !strcmp(mSceneOutInfo.displaymode, MODE_PANEL)) {
2207 cvbsMode = true;
2208 }
2209
2210 /* not enable phy in systemcontrol by default
2211 * as phy will be enabled in driver when set mode
2212 * only enable phy if phy is disabled but not enabled
2213 */
2214 bool phy_enabled_already = true;
2215
2216 // 1. update hdmi frac_rate_policy
2217 char frac_rate_policy[MESON_MODE_LEN] = {0};
2218 char cur_frac_rate_policy[MESON_MODE_LEN] = {0};
2219 bool frac_rate_policy_change = false;
2220 std::string policy;
2221
2222 if (mReason != OUTPUT_CHANGE_BY_HWC) {
2223 getDisplayAttribute(DISPLAY_FRAC_RATE_POLICY, policy);
2224 strcpy(cur_frac_rate_policy, policy.c_str());
2225 getBootEnv(UBOOTENV_FRAC_RATE_POLICY, frac_rate_policy);
2226 if (strstr(frac_rate_policy, cur_frac_rate_policy) == NULL) {
2227 setDisplayAttribute(DISPLAY_FRAC_RATE_POLICY, frac_rate_policy);
2228 frac_rate_policy_change = true;
2229 } else {
2230 MESON_LOGI("cur frac_rate_policy is equals\n");
2231 }
2232 } else {
2233 getDisplayAttribute(DISPLAY_FRAC_RATE_POLICY, policy);
2234 strcpy(cur_frac_rate_policy, policy.c_str());
2235 char defVal[] = "2";
2236 sys_get_string_prop_default(HDMI_FRC_POLICY_PROP,frac_rate_policy, defVal);
2237 if (strstr(frac_rate_policy,"2")) {
2238 getBootEnv(UBOOTENV_FRAC_RATE_POLICY, frac_rate_policy);
2239 }
2240 MESON_LOGI("get frc policy from hwc is %s and current value is %s\n",frac_rate_policy, cur_frac_rate_policy);
2241 if (strstr(frac_rate_policy, cur_frac_rate_policy) == NULL) {
2242 frac_rate_policy_change = true;
2243 }
2244 }
2245
2246 // 2. set hdmi final color space
2247 char curColorAttribute[MESON_MODE_LEN] = {0};
2248 char final_deepcolor[MESON_MODE_LEN] = {0};
2249 bool attr_change = false;
2250
2251 std::string cur_ColorAttribute;
2252 getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute);
2253 strcpy(curColorAttribute, cur_ColorAttribute.c_str());
2254 strcpy(final_deepcolor, mSceneOutInfo.deepcolor);
2255 MESON_LOGI("curDeepcolor[%s] final_deepcolor[%s]\n", curColorAttribute, final_deepcolor);
2256
2257 if (strstr(curColorAttribute, final_deepcolor) == NULL) {
2258 MESON_LOGI("set color space from:%s to %s\n", curColorAttribute, final_deepcolor);
2259 // setDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, final_deepcolor);
2260 cur_ColorAttribute = final_deepcolor;
2261 attr_change = true;
2262 } else {
2263 MESON_LOGI("cur deepcolor is equals\n");
2264 }
2265
2266 // 3. update hdr strategy
2267 bool hdr_policy_change = false;
2268 std::string cur_hdr_policy;
2269 getDisplayAttribute(DISPLAY_HDR_POLICY, cur_hdr_policy);
2270 MESON_LOGI("cur hdr policy:%s\n", cur_hdr_policy.c_str());
2271
2272 std::string cur_hdr_force_mode;
2273 getDisplayAttribute(DISPLAY_FORCE_HDR_MODE, cur_hdr_force_mode);
2274 MESON_LOGI("cur hdr force mode:%s\n", cur_hdr_force_mode.c_str());
2275
2276 std::string cur_amdv_mode;
2277 getDisplayAttribute(DISPLAY_AMDV_MODE, cur_amdv_mode);
2278 MESON_LOGI("cur dv mode:%s\n", cur_amdv_mode.c_str());
2279
2280 std::string cur_amdv_policy;
2281 getDisplayAttribute(DISPLAY_AMDV_POLICY, cur_amdv_policy);
2282 MESON_LOGI("cur dv policy:%s\n", cur_amdv_policy.c_str());
2283
2284 char hdr_force_mode[MESON_MODE_LEN] = {0};
2285 gethdrforcemode(hdr_force_mode);
2286
2287 char hdr_policy[MESON_MODE_LEN] = {0};
2288 getHdrStrategy(hdr_policy);
2289
2290 if (!isDVEnable()) {
2291 if (strstr(cur_hdr_policy.c_str(), hdr_policy) == NULL) {
2292 MESON_LOGI("set hdr policy from:%s to %s\n", cur_hdr_policy.c_str(), hdr_policy);
2293 hdr_policy_change = true;
2294 } else if (!strcmp(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]) && (strstr(cur_hdr_force_mode.c_str(), hdr_force_mode) == NULL)) {
2295 MESON_LOGI("set hdr force mode from:%s to %s\n", cur_hdr_force_mode.c_str(), hdr_force_mode);
2296 hdr_policy_change = true;
2297 }
2298 } else {
2299 if (strstr(cur_amdv_policy.c_str(), hdr_policy) == NULL) {
2300 MESON_LOGI("set dv policy from:%s to %s\n", cur_amdv_policy.c_str(), hdr_policy);
2301 hdr_policy_change = true;
leng.fangd8ab2872024-06-28 16:23:43 +08002302 } else if ((mSceneOutInfo.amdv_type != AMDV_SET_DISABLE)
leng.fang91856072024-06-07 14:12:54 +08002303 && (!strcmp(hdr_policy, AMDV_POLICY_FORCE_MODE)
2304 && (strstr(cur_amdv_mode.c_str(), hdr_force_mode) == NULL))) {
2305 MESON_LOGI("set dv force mode from:%s to %s\n", cur_amdv_mode.c_str(), hdr_force_mode);
2306 hdr_policy_change = true;
2307 }
2308 }
2309
2310 //update hdr priority
2311 bool hdr_priority_change = false;
2312 meson_hdr_priority_e cur_hdr_priority;
2313 cur_hdr_priority = (meson_hdr_priority_e)getCurrentHdrPriority();
2314
2315 meson_hdr_priority_e hdr_priority;
2316 hdr_priority = (meson_hdr_priority_e)getHdrPriority();
2317
2318 if (cur_hdr_priority != hdr_priority) {
2319 SYS_LOGI("set hdr priority from:%x to %x\n", cur_hdr_priority, hdr_priority);
2320 hdr_priority_change = true;
2321 }
2322
2323 // 4. check dv
2324 int amdv_type = AMDV_SET_DISABLE;
2325 bool amdv_change = false;
2326
leng.fangd8ab2872024-06-28 16:23:43 +08002327 amdv_type = mSceneOutInfo.amdv_type;
leng.fang91856072024-06-07 14:12:54 +08002328 amdv_change = checkDVStatusChanged(amdv_type);
2329 if (isMboxSupportDV() && amdv_change && (hdr_priority == MESON_DOLBY_VISION_PRIORITY)) {
2330 //4.1 set avmute when signal change at boot
2331 if ((OUTPUT_MODE_STATE_INIT == mState)
2332 && (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]))) {
2333 // setDisplayAttribute(DISPLAY_HDMI_AVMUTE, "1");
2334 }
2335 //4.2 set dummy_l mode when dv change at UI switch
2336 if ((OUTPUT_MODE_STATE_SWITCH == mState) && amdv_change) {
2337 setDisplayMode("dummy_l");
2338 }
2339 //4.3 enable or disable dv core
2340 if (AMDV_SET_DISABLE != amdv_type) {
2341 enableDV(amdv_type);
2342 } else {
2343 disableDV(amdv_type);
2344 }
2345
2346 MESON_LOGI("isDVEnable: %d", isDVEnable());
2347 } else {
2348 amdv_change = false;
2349 MESON_LOGI("cur DvMode is equals\n");
2350 }
2351
2352 // 5. check hdmi output mode
2353 char final_displaymode[MESON_MODE_LEN] = {0};
2354 char curDisplayMode[MESON_MODE_LEN] = {0};
2355 bool modeChange = false;
2356
2357 getDisplayMode(curDisplayMode);
2358 strcpy(final_displaymode, mSceneOutInfo.displaymode);
2359 MESON_LOGI("curMode:[%s] ,final_displaymode[%s]\n", curDisplayMode, final_displaymode);
2360
2361 if (!isMatchMode(curDisplayMode, final_displaymode)) {
2362 modeChange = true;
2363 } else {
2364 MESON_LOGI("cur mode is equals\n");
2365 }
2366
2367 //6. check any change
2368 bool isNeedChange = false;
2369
2370 if (amdv_change || modeChange || attr_change || frac_rate_policy_change || hdr_policy_change || hdr_priority_change) {
2371 isNeedChange = true;
2372 } else if (force) {
2373 isNeedChange = true;
2374 MESON_LOGD("force changed");
2375 } else {
2376 MESON_LOGI("nothing need to be changed\n");
2377 }
2378
2379 // 8. set hdmi final output mode
2380 if (isNeedChange) {
2381 //apply hdr policy to driver sysfs
2382 if (hdr_policy_change) {
2383 if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) {
2384 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
2385 if (isDVEnable()) {
2386 setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
2387 }
2388 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) {
2389 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
2390 if (isDVEnable()) {
2391 setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
2392 }
2393 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]) || strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) {
2394 char hdr_force_mode[MESON_MODE_LEN] = {0};
2395 gethdrforcemode(hdr_force_mode);
2396 setDisplayAttribute(DISPLAY_FORCE_HDR_MODE, hdr_force_mode);
2397 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]);
2398 if (isDVEnable()) {
2399 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE);
2400 if (strstr(hdr_force_mode, FORCE_AMDV)) {
2401 setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_AMDV);
2402 } else if (strstr(hdr_force_mode, FORCE_HDR10)) {
2403 setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_HDR10);
2404 } else if (strstr(hdr_force_mode, AMDV_DISABLE_FORCE_SDR)) {
2405 // 8bit or not
2406 // std::string cur_ColorAttribute;
2407 // getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute);
2408 if (cur_ColorAttribute.find("8bit", 0) != std::string::npos) {
2409 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_8BIT);
2410 } else {
2411 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_10BIT);
2412 }
2413 }
2414 }
2415 }
2416 }
2417
leng.fang9cf09e22024-07-17 20:01:11 +08002418 if (attr_change || modeChange || frac_rate_policy_change || force)
leng.fang91856072024-06-07 14:12:54 +08002419 mAdapter->setColorAttribute(final_deepcolor);
2420
2421 //apply hdr priority to driver sysfs
2422 if (hdr_priority_change) {
2423 char tmp[MESON_MODE_LEN] = {0};
2424 sprintf(tmp, "%d", hdr_priority);
2425 setDisplayAttribute(DISPLAY_HDR_PRIORITY, tmp);
2426 }
2427
2428 //set hdmi mode
2429 setDisplayMode(final_displaymode);
2430 /* phy already turned on after write display/mode node */
2431 phy_enabled_already = true;
2432 } else {
2433 MESON_LOGI("curDisplayMode is equal final_displaymode, Do not need set it\n");
2434 }
2435
2436 // graphic
2437 char final_Mode[MESON_MODE_LEN] = {0};
2438 getDisplayMode(final_Mode);
2439 char defVal[] = "0x0";
2440 if (sys_get_bool_prop(PROP_DISPLAY_SIZE_CHECK, true)) {
2441 char resolution[MESON_MODE_LEN] = {0};
2442 char defaultResolution[MESON_MODE_LEN] = {0};
2443 char finalResolution[MESON_MODE_LEN] = {0};
2444 int w = 0, h = 0, w1 =0, h1 = 0;
2445 sysfs_get_string(SYS_DISPLAY_RESOLUTION, resolution, MESON_MODE_LEN);
2446 sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal);
2447 sscanf(resolution, "%dx%d", &w, &h);
2448 sscanf(defaultResolution, "%dx%d", &w1, &h1);
2449 if ((w != w1) || (h != h1)) {
2450 if (strstr(final_displaymode, "null") && w1 != 0) {
2451 sprintf(finalResolution, "%dx%d", w1, h1);
2452 } else {
2453 sprintf(finalResolution, "%dx%d", w, h);
2454 }
2455 sys_set_prop(PROP_DISPLAY_SIZE, finalResolution);
2456 }
2457 }
2458 sys_set_prop(PROP_DISPLAY_ALLM, isTvSupportALLM() ? "1" : "0");
2459 sys_set_prop(PROP_DISPLAY_GAME, getGameContentTypeSupport() ? "1" : "0");
2460
2461 char defaultResolution[MESON_MODE_LEN] = {0};
2462 sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal);
2463 MESON_LOGI("set display-size:%s\n", defaultResolution);
2464
2465 int position[4] = { 0, 0, 0, 0 };//x,y,w,h
2466 getPosition(final_displaymode, position);
2467 setPosition(final_displaymode, position[0], position[1],position[2], position[3]);
2468
2469 //audio
2470 char value[MESON_MAX_STR_LEN] = {0};
2471 memset(value, 0, sizeof(0));
2472 getBootEnv(UBOOTENV_DIGITAUDIO, value);
2473 setDigitalMode(value);
2474}
2475
2476void ModePolicy::getFramebufferSize(int disp, uint32_t & width, uint32_t & height) {
2477 char uiMode[PROPERTY_VALUE_MAX] = {0};
2478 if (disp == 0) {
2479 /*primary display*/
2480 if (sys_get_string_prop_default("persist_vendor_hwc_ui_mode", uiMode, "1080") > 0) {
2481 if (!strncmp(uiMode, "720", 3)) {
2482 width = 1280;
2483 height = 720;
2484 } else if (!strncmp(uiMode, "1080", 4)) {
2485 width = 1920;
2486 height = 1080;
2487 } else {
2488 MESON_ASSERT(0, "%s: get not support mode [%s] from vendor.ui_mode",
2489 __func__, uiMode);
2490 }
2491 } else {
2492 width = 1920;
2493 height = 1080;
2494 }
2495 }
2496}
2497
2498int32_t ModePolicy::initialize() {
2499 uint32_t width = 1280;
2500 uint32_t height = 1080;
2501 char log_level[PROPERTY_VALUE_MAX] = { 0 };
2502
leng.fang3e8a4b52024-07-24 14:51:30 +08002503 sys_get_string_prop_default("WESTON_GL_MODE_POLICY_DEBUG", log_level, "2");
leng.fang91856072024-06-07 14:12:54 +08002504 g_activeLevel = atoi(log_level);
2505 mAdapter->setLogLevel(g_activeLevel);
2506
2507 bootenv_init();
2508 getFramebufferSize(mDisplayId, width, height);
2509 mDefaultUI = to_string(height);
2510
2511 mAdapter->initDisplayAttributeInfo(mCrtc, mConnector);
2512 updateHdrCaps();
2513 if (DISPLAY_TYPE_MBOX == mDisplayType) {
2514 // mTxAuth = std::make_shared<HDCPTxAuth>();
2515
2516 setSourceDisplay(OUTPUT_MODE_STATE_INIT);
2517 } else if (DISPLAY_TYPE_TV == mDisplayType) {
2518 setSinkDisplay(true);
2519 }
2520#if 0
2521 } else if (DISPLAY_TYPE_TABLET == mDisplayType) {
2522
2523 } else if (DISPLAY_TYPE_REPEATER == mDisplayType) {
2524 setSourceDisplay(OUTPUT_MODE_STATE_INIT);
2525 }
2526#endif
2527
2528 return 0;
2529}
2530
2531void ModePolicy::setSinkDisplay(bool initState) {
2532 char current_mode[MESON_MODE_LEN] = {0};
2533 char outputmode[MESON_MODE_LEN] = {0};
2534
2535 getDisplayMode(current_mode);
2536 getBootEnv(UBOOTENV_OUTPUTMODE, outputmode);
2537 MESON_LOGD("init tv display old outputmode:%s, outputmode:%s\n", current_mode, outputmode);
2538
2539 if (strlen(outputmode) == 0)
2540 strncpy(outputmode, mDefaultUI.c_str(), MESON_MODE_LEN-1);
2541
2542 setSinkOutputMode(outputmode, initState);
2543}
2544
2545void ModePolicy::setSinkOutputMode(const char* outputmode, bool initState) {
2546 [[maybe_unused]] bool sinkInitState = initState;
2547 MESON_LOGI("set sink output mode:%s, init state:%d\n", outputmode, sinkInitState);
2548
2549 //set output mode
2550 char curMode[MESON_MODE_LEN] = {0};
2551 getDisplayMode(curMode);
2552
2553 MESON_LOGI("curMode = %s outputmode = %s", curMode, outputmode);
2554 if (strstr(curMode, outputmode) == NULL) {
2555 setDisplayMode(outputmode);
2556 }
2557
2558 char defVal[PROPERTY_VALUE_MAX] = "0x0";
2559 if (sys_get_bool_prop(PROP_DISPLAY_SIZE_CHECK, true)) {
2560 char resolution[MESON_MODE_LEN] = {0};
2561 char defaultResolution[MESON_MODE_LEN] = {0};
2562 char finalResolution[MESON_MODE_LEN] = {0};
2563 int w = 0, h = 0, w1 =0, h1 = 0;
2564 sysfs_get_string(SYS_DISPLAY_RESOLUTION, resolution, MESON_MODE_LEN);
2565
2566 sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal);
2567 sscanf(resolution, "%dx%d", &w, &h);
2568 sscanf(defaultResolution, "%dx%d", &w1, &h1);
2569 if ((w != w1) || (h != h1)) {
2570 if (strstr(outputmode, "null") && w1 != 0) {
2571 sprintf(finalResolution, "%dx%d", w1, h1);
2572 } else {
2573 sprintf(finalResolution, "%dx%d", w, h);
2574 }
2575 sys_set_prop(PROP_AMDV_PRIORITY, finalResolution);
2576 }
2577 }
2578
2579 char defaultResolution[MESON_MODE_LEN] = {0};
2580 sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal);
2581 MESON_LOGI("set display-size:%s\n", defaultResolution);
2582
2583 //update hwc windows size
2584 int position[4] = { 0, 0, 0, 0 };//x,y,w,h
2585 getPosition(outputmode, position);
2586 setPosition(outputmode, position[0], position[1],position[2], position[3]);
2587
2588 //update hdr policy
2589 if ((isMboxSupportDV() == false)) {
2590 if (sys_get_bool_prop(PROP_AMDV_FEATURE, false)) {
2591 char hdr_policy[MESON_MODE_LEN] = {0};
2592 getHdrStrategy(hdr_policy);
2593 if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) {
2594 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
2595 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) {
2596 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
2597 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE])) {
2598 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]);
2599 }
2600 } else {
2601 initHdrSdrMode();
2602 }
2603 }
2604
2605 if (isMboxSupportDV()) {
2606 if (isTvDVEnable()) {
2607 setTvDVEnable();
2608 } else {
2609 setTvDVDisable();
2610 }
2611 }
2612
2613 //audio
2614 char value[MESON_MAX_STR_LEN] = {0};
2615 memset(value, 0, sizeof(0));
2616 getBootEnv(UBOOTENV_DIGITAUDIO, value);
2617 setDigitalMode(value);
2618
2619 //save output mode
2620 char finalMode[MESON_MODE_LEN] = {0};
2621 getDisplayMode(finalMode);
2622 if (DISPLAY_TYPE_TABLET != mDisplayType) {
2623 setBootEnv(UBOOTENV_OUTPUTMODE, (char *)finalMode);
2624 }
2625 if (strstr(finalMode, "cvbs") != NULL) {
2626 setBootEnv(UBOOTENV_CVBSMODE, (char *)finalMode);
2627 } else if (strstr(finalMode, "hz") != NULL) {
2628 setBootEnv(UBOOTENV_HDMIMODE, (char *)finalMode);
2629 }
2630
2631 MESON_LOGI("set output mode:%s done\n", finalMode);
2632}
2633
2634bool ModePolicy::isHdmiUsed() {
2635 bool ret = true;
2636 char hdmi_state[MESON_MODE_LEN] = {0};
2637
2638 sysfs_get_string(DISPLAY_HDMI_USED, hdmi_state, MESON_MODE_LEN);
2639
2640 if (strstr(hdmi_state, "1") == NULL) {
2641 ret = false;
2642 }
2643
2644 return ret;
2645}
2646
2647bool ModePolicy::isConnected() {
2648 bool ret = ((mConnectorType == CONN_TYPE_HDMI) &&
2649 (mConnector->connection == DRM_MODE_CONNECTED));
2650 return ret;
2651}
2652
2653bool ModePolicy::isVMXCertification() {
2654 return sys_get_bool_prop(PROP_VMX, false);
2655}
2656
2657bool ModePolicy::isHdmiEdidParseOK() {
2658 bool ret = true;
2659
2660 char edidParsing[MESON_MODE_LEN] = {0};
2661 sysfs_get_string(DISPLAY_EDID_STATUS, edidParsing, MESON_MODE_LEN);
2662
2663 if (strcmp(edidParsing, "ok")) {
2664 ret = false;
2665 }
2666
2667 return ret;
2668}
2669
2670bool ModePolicy::isBestPolicy() {
2671 char isBestMode[MESON_MODE_LEN] = {0};
2672 if (DISPLAY_TYPE_TV == mDisplayType) {
2673 return false;
2674 }
2675
2676 return !getBootEnv(UBOOTENV_ISBESTMODE, isBestMode) || strcmp(isBestMode, "true") == 0;
2677}
2678
2679bool ModePolicy::isBestColorSpace() {
2680 bool ret = false;
2681 char user_colorattr[MESON_MODE_LEN] = {0};
2682 if (DISPLAY_TYPE_TV == mDisplayType) {
2683 return false;
2684 }
2685
2686 ret = getBootEnv(UBOOTENV_USER_COLORATTRIBUTE, user_colorattr);
2687
2688 if (!ret) {
2689 return true;
2690 } else if (strstr(user_colorattr, "bit") == NULL) {
2691 return true;
2692 }
2693
2694 return false;
2695}
2696
2697void ModePolicy::setDefaultMode() {
2698 MESON_LOGE("EDID parsing error detected\n");
2699
2700 // check hdmi output mode
2701 char curDisplayMode[MESON_MODE_LEN] = {0};
2702 getDisplayMode(curDisplayMode);
2703
2704 if (!isMatchMode(curDisplayMode, MESON_DEFAULT_HDMI_MODE)) {
2705 //set default color format
2706 setDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, MESON_DEFAULT_COLOR_FORMAT);
2707 //set default resolution
2708 setDisplayMode(MESON_DEFAULT_HDMI_MODE);
2709
2710 //update display position
2711 int position[4] = { 0, 0, 0, 0 };//x,y,w,h
2712 getPosition(MESON_DEFAULT_HDMI_MODE, position);
2713 setPosition(MESON_DEFAULT_HDMI_MODE, position[0], position[1],position[2], position[3]);
2714 } else {
2715 MESON_LOGI("cur mode is default mode\n");
2716 }
2717}
2718
leng.fang3c0ab6d2024-08-01 16:29:00 +08002719void ModePolicy::setDisplay(output_mode_state state)
2720{
2721 if ((state == OUTPUT_MODE_STATE_INIT) ||
2722 (state == OUTPUT_MODE_STATE_POWER)) {
2723 memset(&mConData, 0, sizeof(meson_policy_in));
2724 memset(&mDvInfo, 0, sizeof(hdmi_amdv_info_t));
2725 mState = state;
2726 mConData.state = static_cast<meson_mode_state>(state);
leng.fang91856072024-06-07 14:12:54 +08002727
leng.fang3c0ab6d2024-08-01 16:29:00 +08002728 getConnectorData(&mConData, &mDvInfo);
2729 if (isTvSupportDV() && isMboxSupportDV()) {
2730 strcpy(mDvInfo.amdv_enable, "1");
2731 mConData.hdr_info.is_amdv_enable = isDVEnable();
2732 }
2733
2734 strcpy(mConData.cur_displaymode, mConData.con_info.ubootenv_hdmimode);
2735 }
2736
2737 // TOD sceneProcess
2738 if (isBestPolicy()) {
2739 if (state == OUTPUT_MODE_STATE_INIT || mPolicy == MESON_POLICY_INVALID) {
2740 mPolicy = MESON_POLICY_MIX;
2741 }
2742 } else {
2743 mPolicy = MESON_POLICY_INVALID;
2744 }
2745
2746 meson_mode_set_policy(mModeConType, mPolicy);
2747 meson_mode_set_policy_input(mModeConType, &mConData);
2748 meson_mode_get_policy_output(mModeConType, &mSceneOutInfo);
2749
2750 //5. apply settings to driver
2751 applyDisplaySetting(state == OUTPUT_MODE_STATE_POWER);
2752}
leng.fang91856072024-06-07 14:12:54 +08002753/*
2754 * OUTPUT_MODE_STATE_INIT for boot
2755 * OUTPUT_MODE_STATE_POWER for hdmi plug and suspend/resume
2756 */
2757void ModePolicy::setSourceDisplay(output_mode_state state) {
2758 std::lock_guard<std::mutex> lock(mMutex);
2759
2760 //1. hdmi used and hpd = 0
2761 //set dummy_l mode
2762 if ((isHdmiUsed() == true) && (isConnected() == false)) {
leng.fang3c0ab6d2024-08-01 16:29:00 +08002763 MESON_LOGD("hdmi usd, set cvbs");
2764 setDisplay(state);
leng.fang91856072024-06-07 14:12:54 +08002765 MESON_LOGI("hdmi used but plugout when boot\n");
2766 return;
2767 }
2768
2769 //2. hdmi edid parse error and hpd = 1
2770 //set default reolsution and color format
2771 if ((isHdmiEdidParseOK() == false) &&
2772 (isConnected() == true)) {
2773 setDefaultMode();
2774 return;
2775 }
2776
2777 //3. update hdmi info when boot and hdmi plug/suspend/resume
2778 if ((state == OUTPUT_MODE_STATE_INIT) ||
2779 (state == OUTPUT_MODE_STATE_POWER)) {
2780 memset(&mConData, 0, sizeof(meson_policy_in));
2781 memset(&mDvInfo, 0, sizeof(hdmi_amdv_info_t));
2782 mState = state;
2783 mConData.state = static_cast<meson_mode_state>(state);
2784
2785 getConnectorData(&mConData, &mDvInfo);
2786 if (isTvSupportDV() && isMboxSupportDV()) {
2787 strcpy(mDvInfo.amdv_enable, "1");
2788 mConData.hdr_info.is_amdv_enable = isDVEnable();
2789 }
2790
2791 strcpy(mConData.cur_displaymode, mConData.con_info.ubootenv_hdmimode);
2792 }
2793
2794 // TOD sceneProcess
2795 if (isBestPolicy()) {
2796 if (state == OUTPUT_MODE_STATE_INIT || mPolicy == MESON_POLICY_INVALID) {
2797 mPolicy = MESON_POLICY_MIX;
2798 }
2799 } else {
2800 mPolicy = MESON_POLICY_INVALID;
2801 }
2802
2803 meson_mode_set_policy(mModeConType, mPolicy);
2804 meson_mode_set_policy_input(mModeConType, &mConData);
2805 meson_mode_get_policy_output(mModeConType, &mSceneOutInfo);
2806
2807 //5. apply settings to driver
2808 applyDisplaySetting(state == OUTPUT_MODE_STATE_POWER);
2809}
2810
leng.fang5ec9b6c2024-07-29 14:25:00 +08002811void ModePolicy::setSourceOutputModeNoLock(const char* outputmode, bool force) {
leng.fang91856072024-06-07 14:12:54 +08002812 if (DISPLAY_TYPE_TV == mDisplayType) {
2813 setSinkOutputMode(outputmode, false);
2814 } else {
2815
2816 getConnectorUserData(&mConData, &mDvInfo);
2817
2818 getHdrUserInfo(&mConData.hdr_info);
2819
2820 mState = OUTPUT_MODE_STATE_SWITCH;
2821 mConData.state = static_cast<meson_mode_state>(mState);
2822
2823 strcpy(mConData.cur_displaymode, outputmode);
2824 meson_mode_set_policy_input(mModeConType, &mConData);
2825 meson_mode_get_policy_output(mModeConType, &mSceneOutInfo);
2826
2827 applyDisplaySetting(force);
2828 }
2829}
2830
leng.fang5ec9b6c2024-07-29 14:25:00 +08002831void ModePolicy::setSourceOutputMode(const char* outputmode, bool force) {
2832 std::lock_guard<std::mutex> lock(mMutex);
2833
2834 setSourceOutputModeNoLock(outputmode, force);
2835}
2836
leng.fang91856072024-06-07 14:12:54 +08002837void ModePolicy::getConnectorUserData(struct meson_policy_in* data, hdmi_amdv_info_t *dinfo) {
2838 if (!data || !dinfo) {
2839 MESON_LOGE("%s data is NULL\n", __FUNCTION__);
2840 return;
2841 }
2842
2843 bool ret = false;
2844
2845 //hdmi color space best policy flag
2846 data->con_info.is_bestcolorspace = isBestColorSpace();
2847
2848 MESON_LOGI("isbestColorspace:%d\n",
2849 data->con_info.is_bestcolorspace);
2850
2851 getDisplayMode(mCurrentMode);
2852 ret = getBootEnv(UBOOTENV_HDMIMODE, data->con_info.ubootenv_hdmimode);
2853 if (!ret) {
2854 //if env is null,use none as default value
2855 strcpy(data->con_info.ubootenv_hdmimode, "none");
2856 }
2857 getBootEnv(UBOOTENV_CVBSMODE, data->con_info.ubootenv_cvbsmode);
2858 MESON_LOGI("hdmi_current_mode:%s, ubootenv hdmimode:%s cvbsmode:%s\n",
2859 mCurrentMode,
2860 data->con_info.ubootenv_hdmimode,
2861 data->con_info.ubootenv_cvbsmode);
2862
2863 ret = getBootEnv(UBOOTENV_USER_COLORATTRIBUTE, data->con_info.ubootenv_colorattr);
2864 if (!ret) {
2865 //if env is null,use none as default value
2866 strcpy(data->con_info.ubootenv_colorattr, "none");
2867 }
2868 MESON_LOGI("ubootenv_colorattribute:%s\n",
2869 data->con_info.ubootenv_colorattr);
2870
2871 //if no dolby_status env set to std for enable dv
2872 //if box support dv
2873 char amdv_enable[MESON_MODE_LEN];
2874 ret = getBootEnv(UBOOTENV_DV_ENABLE, amdv_enable);
2875 if (ret) {
2876 strcpy(dinfo->amdv_enable, amdv_enable);
2877 } else if (isMboxSupportDV()) {
2878 strcpy(dinfo->amdv_enable, "1");
2879 } else {
2880 strcpy(dinfo->amdv_enable, "0");
2881 }
2882 MESON_LOGI("dv_enable:%s\n", dinfo->amdv_enable);
2883
2884 char ubootenv_amdv_type[MESON_MODE_LEN];
2885 ret = getBootEnv(UBOOTENV_USER_DV_TYPE, ubootenv_amdv_type);
2886 if (ret) {
2887 strcpy(dinfo->ubootenv_amdv_type, ubootenv_amdv_type);
2888 } else if (isMboxSupportDV()) {
2889 strcpy(dinfo->ubootenv_amdv_type, "1");
2890 } else {
2891 strcpy(dinfo->ubootenv_amdv_type, "0");
2892 }
2893 MESON_LOGI("ubootenv_dv_type:%s\n", dinfo->ubootenv_amdv_type);
2894}
2895
2896void ModePolicy::drmMode2MesonMode(meson_mode_info_t &mesonMode, drm_mode_info_t &drmMode) {
2897 strncpy(mesonMode.name, drmMode.name, MESON_MODE_LEN);
2898 mesonMode.dpi_x = drmMode.dpiX;
2899 mesonMode.dpi_y = drmMode.dpiY;
2900 mesonMode.pixel_w = drmMode.pixelW;
2901 mesonMode.pixel_h = drmMode.pixelH;
2902 mesonMode.refresh_rate = drmMode.refreshRate;
2903 mesonMode.group_id = drmMode.groupId;
2904}
2905
2906void ModePolicy::getSupportedModes() {
2907 //pthread_mutex_lock(&mEnvLock);
2908 std::map<uint32_t, drm_mode_info_t> connecterModeList;
2909
2910 /* reset ModeList */
2911 mModes.clear();
2912 if (mConnector->connection == DRM_MODE_CONNECTED) {
2913 getModes(mConnector, connecterModeList);
2914
2915 for (auto it = connecterModeList.begin(); it != connecterModeList.end(); it++) {
2916 // All modes are supported
2917 if (isModeSupported(it->second)) {
2918 mModes.emplace(mModes.size(), it->second);
2919 }
2920 }
2921 }
2922
2923 /* transfer to meson_mode_info_t */
2924 auto conPtr = &mConData.con_info;
2925 conPtr->modes_size = mModes.size();
2926 if (conPtr->modes_size > conPtr->modes_capacity) {
2927 // realloc memory
2928 void * buff = realloc(conPtr->modes, conPtr->modes_size * sizeof(meson_mode_info_t));
2929 MESON_ASSERT(buff, "modePolicy realloc but has no memory");
2930 conPtr->modes = (meson_mode_info_t *) buff;
2931 conPtr->modes_capacity = conPtr->modes_size;
2932 }
2933
2934 int i = 0;
2935 for (auto it = mModes.begin(); it != mModes.end(); it++) {
2936 drmMode2MesonMode(conPtr->modes[i], it->second);
2937 i++;
2938 }
2939}
2940
2941bool ModePolicy::getModeNameForPix(char *name,
2942 int32_t width, int32_t height, uint32_t refresh, uint32_t flags)
2943{
2944 std::map<uint32_t, drm_mode_info_t> connecterModeList;
2945 drm_mode_info_t mode;
2946 int current_interlaced;
2947 bool ret = false;
2948
2949 if (!mConnector || mConnector->connection != DRM_MODE_CONNECTED)
2950 return false;
2951
2952 drmModeModeInfoPtr drmModes = mConnector->modes;
2953
2954 for (int i = 0;i < mConnector->count_modes; i++) {
2955 current_interlaced = (drmModes[i].flags & DRM_MODE_FLAG_INTERLACE);
2956 if (drmModes[i].hdisplay == width && drmModes[i].vdisplay == height &&
2957 drmModes[i].vrefresh == refresh &&
2958 current_interlaced == (flags & DRM_MODE_FLAG_INTERLACE)) {
2959 strcpy(name, drmModes[i].name);
2960 ret = true;
2961 break;
2962 }
2963 }
2964 return ret;
2965}
2966
2967bool ModePolicy::isModeSupported(drm_mode_info_t mode) {
2968 bool ret = false;
2969 uint32_t i;
2970
2971 for (i = 0; i < ARRAY_SIZE(DISPLAY_MODE_LIST); i++) {
2972 if (!strcmp(DISPLAY_MODE_LIST[i], mode.name)) {
2973 ret = true;
2974 break;
2975 }
2976 }
2977
2978 return ret;
2979}
2980
2981int32_t bindCrtcAndConnector(drmModeCrtc *crtc, drmModeConnector *conn)
2982{
2983 int ret = -1;
2984 MESON_LOGI("bindCrtcAndConnector:%p, %p\n", crtc, conn);
2985 if (g_Policy.get()) {
2986 ret = g_Policy->bindConnector(conn);
2987 ret |= g_Policy->bindCrtc(crtc);
2988 }
2989 return ret;
2990}
2991
2992void initModePolicyFun(drmModeCrtc *crtc, drmModeConnector *conn, CompositorFunctionCallBack callback)
2993{
2994 if (!g_Adapter.get())
2995 g_Adapter = std::make_shared<DisplayAdapter>(crtc, conn);
2996
2997 if (!g_Policy.get())
2998 g_Policy = std::make_shared<ModePolicy>(g_Adapter, 0);
2999
3000 if (g_Policy.get() && g_Adapter.get()) {
3001 g_Adapter->registerCallBack(callback);
3002 bindCrtcAndConnector(crtc, conn);
3003 }
3004}
3005
3006void initModePolicy(drmModeCrtc *crtc, drmModeConnector *conn, CompositorFunctionCallBack callback)
3007{
3008 //initModePolicyFun(crtc, conn,callback);
3009 if (g_Policy.get()) {
3010 g_Policy->initialize();
3011 }
3012}
3013
3014void onHotplug(bool connected)
3015{
3016 if (g_Policy.get())
3017 g_Policy->onHotplug(connected);
3018}
3019
3020void getPreferredBootConfig(char *name)
3021{
3022 std::string mode;
3023 if (g_Policy.get()) {
3024 if (g_Policy->getPreferredBootConfig(mode) == 0)
3025 strcpy(name, mode.c_str());
3026 }
3027}
3028
3029void setHdrConversionPolicy(bool passthrough, int32_t forceType)
3030{
3031 if (g_Policy.get())
3032 g_Policy->setHdrConversionPolicy(passthrough, forceType);
3033}
3034
3035void setDvMode(int amdv_mode)
3036{
3037 std::string mode = to_string(amdv_mode);
3038 if (g_Policy.get())
3039 g_Policy->setDvMode(mode);
3040}
3041
3042void setColorSpace(char *colorspace)
3043{
3044 std::string color = colorspace;
3045 if (g_Policy.get())
3046 g_Policy->setColorSpace(color);
3047}
3048
3049void setBootConfig(char *mode, bool auto_mode)
3050{
3051 std::string config = mode;
3052 if (g_Policy.get()) {
3053 if (auto_mode)
3054 g_Policy->clearBootConfig();
3055 else
3056 g_Policy->setBootConfig(config);
3057 }
3058}
3059
3060bool setActiveConfig(char *mode)
3061{
3062 std::string config = mode;
3063 if (g_Policy.get()) {
3064 g_Policy->setActiveConfig(config);
3065 return true;
3066 }
3067 return false;
3068}
3069
3070bool setPolicyByAppName(const char *name, int state)
3071{
3072 if (g_Policy.get()) {
3073 if (state == 1 && !strcmp(name, "netflix")) {
3074 g_Policy->setPolicy(MESON_POLICY_BEST);
3075 } else {
3076 g_Policy->setPolicy(MESON_POLICY_MIX);
3077 }
3078 return true;
3079 }
3080 return false;
3081}
3082
3083bool updateEnv()
3084{
3085 if (g_Policy.get())
3086 return g_Policy->updateEnv();
3087 return false;
3088}
3089
3090bool getModeNameForPix(char *name,
3091 int32_t width, int32_t height, uint32_t refresh, uint32_t flags)
3092{
3093 if (g_Policy.get())
3094 return g_Policy->getModeNameForPix(name, width, height, refresh / 1000, flags);
3095 return false;
3096}