blob: c24ad213de1d041be7a8cad62ef8aa5de34cc42c [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
1281 // 2.2 save output mode
1282 if (DISPLAY_TYPE_TABLET != mDisplayType) {
1283 setBootEnv(UBOOTENV_OUTPUTMODE, (char *)outputMode);
1284 }
1285
1286 // 2.3 save dv status/dv_type
1287 // In follow sink mode: 0:disable 1:STD(or enable dv) 2:LL YUV 3: LL RGB
1288 // In follow source mode: dv is disable in uboot.
1289 if (isMboxSupportDV()) {
1290 char hdr_force_mode[MESON_MODE_LEN] = {0};
1291 memset(hdr_force_mode, 0, MESON_MODE_LEN);
1292 getBootEnv(UBOOTENV_HDR_FORCE_MODE, hdr_force_mode);
1293 getHdrStrategy(hdr_policy);
1294 if (!strcmp(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]) ||
1295 (!strcmp(hdr_policy, AMDV_POLICY_FORCE_MODE) && !strcmp(hdr_force_mode, FORCE_HDR10))) {
1296 sprintf(dvstatus, "%d", 0);
1297 } else {
leng.fangd8ab2872024-06-28 16:23:43 +08001298 sprintf(dvstatus, "%d", mSceneOutInfo.amdv_type);
leng.fang91856072024-06-07 14:12:54 +08001299 }
1300 setBootEnv(UBOOTENV_DOLBYSTATUS, dvstatus);
1301
1302 if (strlen(dvenable) > 0)
1303 setBootEnv(UBOOTENV_DV_ENABLE, dvenable);
1304
1305 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 +08001306 dvstatus, mSceneOutInfo.amdv_type, mDvInfo.amdv_enable, hdr_policy, hdr_force_mode);
leng.fang91856072024-06-07 14:12:54 +08001307
1308 } else {
1309 MESON_LOGI("MBOX is not support dv, dvstatus %s dv_type %d dv_enable %s\n",
leng.fangd8ab2872024-06-28 16:23:43 +08001310 dvstatus, mSceneOutInfo.amdv_type, mDvInfo.amdv_enable);
leng.fang91856072024-06-07 14:12:54 +08001311 }
1312
1313 MESON_LOGI("colorattr: %s, outputMode %s, cd %s, cs %s\n",
1314 colorAttr.c_str(), outputMode, colorDepth, colorSpace);
1315 }
1316}
1317
1318bool ModePolicy::updateEnv()
1319{
1320 if (mDisplayType == DISPLAY_TYPE_MBOX)
1321 saveHdmiParamToEnv();
1322 return true;
1323}
1324
1325void ModePolicy::enableDV(int DvMode) {
1326 if (isMboxSupportDV() == false) {
1327 MESON_LOGI("This platform is not support dv or has no dv ko");
1328 return;
1329 }
1330 MESON_LOGI("DvMode %d", DvMode);
1331
1332 strcpy(mDvInfo.amdv_enable, "1");
1333
1334 //if TV
1335 if (DISPLAY_TYPE_TV == mDisplayType) {
1336 setHdrMode(HDR_MODE_OFF);
1337 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FOLLOW_SINK);
1338 }
1339
1340 //if OTT
1341 char hdr_policy[MESON_MODE_LEN] = {0};
1342 getHdrStrategy(hdr_policy);
1343 if ((DISPLAY_TYPE_MBOX == mDisplayType) || (DISPLAY_TYPE_REPEATER == mDisplayType)) {
1344 switch (DvMode) {
1345 case AMDV_SET_ENABLE:
1346 MESON_LOGI("Dv set Mode [DV_RGB_444_8BIT]\n");
1347 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0");
1348 break;
1349 case AMDV_SET_ENABLE_LL_YUV:
1350 MESON_LOGI("Dv set Mode [LL_YCbCr_422_12BIT]\n");
1351 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0");
1352 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "1");
1353 break;
1354 case AMDV_SET_ENABLE_LL_RGB:
1355 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0");
1356 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "2");
1357 break;
1358 default:
1359 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0");
1360 }
1361
1362 if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) {
1363 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
1364 if (isDVEnable()) {
1365 setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
1366 }
1367 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) {
1368 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
1369 if (isDVEnable()) {
1370 setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
1371 }
1372 } else if (strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) {
1373 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]);
1374 if (isDVEnable()) {
1375 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE);
1376 }
1377 }
1378 }
1379
1380 setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_ENABLE);
1381 if (strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) {
1382 char hdr_force_mode[MESON_MODE_LEN] = {0};
1383 gethdrforcemode(hdr_force_mode);
1384 if (strstr(hdr_force_mode, FORCE_AMDV)) {
1385 setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_AMDV);
1386 } else if (strstr(hdr_force_mode, FORCE_HDR10)) {
1387 setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_HDR10);
1388 } else if (strstr(hdr_force_mode, AMDV_DISABLE_FORCE_SDR)) {
1389 // 8bit or not
1390 std::string cur_ColorAttribute;
1391 getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute);
1392 if (cur_ColorAttribute.find("8bit", 0) != std::string::npos) {
1393 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_8BIT);
1394 } else {
1395 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_10BIT);
1396 }
1397 }
1398 } else {
1399 int amdv_prop = DvMode == AMDV_SET_ENABLE_LL_YUV ? 1 : 0;
1400 setDisplayAttribute(DISPLAY_AMDV_MODE, to_string(amdv_prop));
1401 }
1402
1403 if (DISPLAY_TYPE_TV == mDisplayType) {
1404 setHdrMode(HDR_MODE_AUTO);
1405 }
1406
1407 initGraphicsPriority();
1408}
1409
1410void ModePolicy::disableDV(int DvMode) {
1411 //char tvmode[MESON_MODE_LEN] = {0};
1412 int check_status_count = 0;
1413 [[maybe_unused]] int amdv_type = DvMode;
1414
1415 MESON_LOGI("amdv_type %d", amdv_type);
1416 strcpy(mDvInfo.amdv_enable, "0");
1417
1418 //2. update sysfs
1419 char hdr_policy[MESON_MODE_LEN] = {0};
1420 getHdrStrategy(hdr_policy);
1421
1422 if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) {
1423 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
1424 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) {
1425 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
1426 }
1427
1428 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE);
1429 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_MODE_BYPASS);
1430 usleep(100000);//100ms
1431 std::string dvstatus = "";
1432 getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus);
1433
1434 if (strcmp(dvstatus.c_str(), BYPASS_PROCESS)) {
1435 while (++check_status_count <30) {
1436 usleep(20000);//20ms
1437 getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus);
1438 if (!strcmp(dvstatus.c_str(), BYPASS_PROCESS)) {
1439 break;
1440 }
1441 }
1442 }
1443
1444 MESON_LOGI("dvstatus %s, check_status_count [%d]", dvstatus.c_str(), check_status_count);
1445 setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_DISABLE);
1446
1447 if (DISPLAY_TYPE_TV == mDisplayType) {
1448 setHdrMode(HDR_MODE_AUTO);
1449 }
1450
1451 setSdrMode(SDR_MODE_AUTO);
1452}
1453
1454void ModePolicy::getPosition(const char* curMode, int *position) {
1455 char keyValue[20] = {0};
1456 char ubootvar[100] = {0};
1457 int defaultWidth = 0;
1458 int defaultHeight = 0;
1459 std::map<uint32_t, drm_mode_info_t> connecterModeList;
1460
1461 drm_mode_info_t mode = {
1462 "null",
1463 0, 0,
1464 0, 0,
1465 60.0,
1466 0
1467 };
1468
1469 if (mConnector->connection == DRM_MODE_CONNECTED) {
1470 getModes(mConnector, connecterModeList);
1471
1472 for (auto it = connecterModeList.begin(); it != connecterModeList.end(); it++) {
1473 if (mConnector->connector_type == DRM_MODE_CONNECTOR_TV) {
1474 if (strstr(curMode, it->second.name)) {
1475 strcpy(keyValue, curMode);
1476 mode = it->second;
1477 break;
1478 }
1479 } else {
1480 if (strstr(curMode, it->second.name)) {
1481 if (strstr(it->second.name, MODE_4K2KSMPTE_PREFIX)) {
1482 strcpy(keyValue, "4k2ksmpte");
1483 } else if (strstr(it->second.name, MODE_PANEL)) {
1484 strcpy(keyValue, MODE_PANEL);
1485 } else if (strchr(curMode,'p')) {
1486 strncpy(keyValue, curMode, strchr(curMode,'p') - curMode + 1);
1487 } else if (strchr(curMode,'i')){
1488 strncpy(keyValue, curMode, strchr(curMode,'i') - curMode + 1);
1489 }
1490 mode = it->second;
1491 break;
1492 }
1493 }
1494 }
1495 }
1496
1497 if (keyValue[0] != '0') {
1498 defaultWidth = mode.pixelW;
1499 defaultHeight = mode.pixelH;
1500 } else {
1501 strcpy(keyValue, MODE_1080P_PREFIX);
1502 defaultWidth = FULL_WIDTH_1080;
1503 defaultHeight = FULL_HEIGHT_1080;
1504 }
1505
1506 pthread_mutex_lock(&mEnvLock);
1507 sprintf(ubootvar, "ubootenv.var.%s_x", keyValue);
1508 position[0] = getBootenvInt(ubootvar, 0);
1509 sprintf(ubootvar, "ubootenv.var.%s_y", keyValue);
1510 position[1] = getBootenvInt(ubootvar, 0);
1511 sprintf(ubootvar, "ubootenv.var.%s_w", keyValue);
1512 position[2] = getBootenvInt(ubootvar, defaultWidth);
1513 sprintf(ubootvar, "ubootenv.var.%s_h", keyValue);
1514 position[3] = getBootenvInt(ubootvar, defaultHeight);
1515
1516 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]);
1517
1518 pthread_mutex_unlock(&mEnvLock);
1519
1520}
1521
1522void ModePolicy::setPosition(const char* curMode, int left, int top, int width, int height) {
1523 char x[512] = {0};
1524 char y[512] = {0};
1525 char w[512] = {0};
1526 char h[512] = {0};
1527 sprintf(x, "%d", left);
1528 sprintf(y, "%d", top);
1529 sprintf(w, "%d", width);
1530 sprintf(h, "%d", height);
1531
1532 MESON_LOGI("%s curMode:%s left:%d top:%d width:%d height:%d\n", __FUNCTION__, curMode, left, top, width, height);
1533
1534 char keyValue[20] = {0};
1535 char ubootvar[100] = {0};
1536 bool find = false;
1537 std::map<uint32_t, drm_mode_info_t> connecterModeList;
1538
1539 if (mConnector->connection == DRM_MODE_CONNECTED) {
1540 getModes(mConnector, connecterModeList);
1541
1542 for (auto it = connecterModeList.begin(); it != connecterModeList.end(); it++) {
1543 if (mConnector->connector_type == DRM_MODE_CONNECTOR_TV) {
1544 if (strstr(curMode, it->second.name)) {
1545 strcpy(keyValue, curMode);
1546 find = true;
1547 break;
1548 }
1549 } else {
1550 if (strstr(curMode, it->second.name)) {
1551 if (strstr(it->second.name, MODE_4K2KSMPTE_PREFIX)) {
1552 strcpy(keyValue, "4k2ksmpte");
1553 find = true;
1554 } else if (strstr(it->second.name, MODE_PANEL)) {
1555 strcpy(keyValue, MODE_PANEL);
1556 find = true;
1557 } else if (strchr(curMode,'p')) {
1558 strncpy(keyValue, curMode, strchr(curMode,'p') - curMode + 1);
1559 find = true;
1560 } else if (strchr(curMode,'i')){
1561 strncpy(keyValue, curMode, strchr(curMode,'i') - curMode + 1);
1562 find = true;
1563 }
1564 break;
1565 }
1566 }
1567 }
1568 }
1569
1570 if (!find)
1571 return;
1572
1573 mAdapter->setDisplayRect(left, top, width , height);
1574}
1575
1576void ModePolicy::setDigitalMode(const char* mode) {
1577 if (mode == NULL) return;
1578
1579 if (!strcmp("PCM", mode)) {
1580 sysfs_set_string(AUDIO_DSP_DIGITAL_RAW, "0");
1581 sysfs_set_string(AV_HDMI_CONFIG, "audio_on");
1582 } else if (!strcmp("SPDIF passthrough", mode)) {
1583 sysfs_set_string(AUDIO_DSP_DIGITAL_RAW, "1");
1584 sysfs_set_string(AV_HDMI_CONFIG, "audio_on");
1585 } else if (!strcmp("HDMI passthrough", mode)) {
1586 sysfs_set_string(AUDIO_DSP_DIGITAL_RAW, "2");
1587 sysfs_set_string(AV_HDMI_CONFIG, "audio_on");
1588 }
1589}
1590
1591bool ModePolicy::getDisplayMode(char* mode) {
1592 bool ret = false;
1593
1594 if (mode != NULL) {
1595 ret = mAdapter->getDisplayMode(mode);
1596 MESON_LOGI("%s mode:%s\n", __FUNCTION__, mode);
1597 } else {
1598 MESON_LOGE("%s mode is NULL\n", __FUNCTION__);
1599 }
1600
1601 return ret;
1602}
1603
1604//set hdmi output mode
1605int32_t ModePolicy::setDisplayMode(std::string &mode) {
1606 MESON_LOGI("%s mode:%s\n", __FUNCTION__, mode.c_str());
1607 mAdapter->setDisplayMode(mode);
1608 return 0;
1609}
1610
1611int32_t ModePolicy::setDisplayMode(const char *mode) {
1612 if (!mode) {
1613 MESON_LOGE("ModePolicy::setDisplayMode null mode");
1614 return -EINVAL;
1615 }
1616 std::string displayMode(mode);
1617 return setDisplayMode(displayMode);
1618}
1619
1620bool ModePolicy::setDisplayAttribute(const std::string cmd, const std::string attribute) {
1621 return mAdapter->setDisplayAttribute(cmd, attribute);
1622}
1623bool ModePolicy::getDisplayAttribute(const std::string cmd, std::string& attribute) {
1624 return mAdapter->getDisplayAttribute(cmd, attribute);
1625}
1626
1627bool ModePolicy::isMatchMode(char* curmode, const char* outputmode) {
1628 bool ret = false;
1629 char tmpMode[MESON_MODE_LEN] = {0};
1630
1631 char *pCmp = curmode;
1632 //check line feed key
1633 char *pos = strchr(pCmp, 0x0a);
1634 if (NULL == pos) {
1635 //check return key
1636 char *pos = strchr(pCmp, 0x0d);
1637 if (NULL == pos) {
1638 strcpy(tmpMode, pCmp);
1639 } else {
1640 strncpy(tmpMode, pCmp, pos - pCmp);
1641 }
1642 } else {
1643 strncpy(tmpMode, pCmp, pos - pCmp);
1644 }
1645
1646 MESON_LOGI("curmode:%s, tmpMode:%s, outputmode:%s\n", curmode, tmpMode, outputmode);
1647
1648 if (!strcmp(tmpMode, outputmode)) {
1649 ret = true;
1650 }
1651
1652 return ret;
1653}
1654
1655bool ModePolicy::isTvSupportALLM() {
1656 char allm_mode_cap[PROP_VALUE_MAX];
1657 memset(allm_mode_cap, 0, PROP_VALUE_MAX);
1658 int ret = 0;
1659
1660 sysfs_get_string(AUTO_LOW_LATENCY_MODE_CAP, allm_mode_cap, PROP_VALUE_MAX);
1661
1662 for (int i = 0; i < ARRAY_SIZE(ALLM_MODE_CAP); i++) {
1663 if (!strncmp(allm_mode_cap, ALLM_MODE_CAP[i], strlen(ALLM_MODE_CAP[i]))) {
1664 ret = i;
1665 }
1666 }
1667
1668 return (ret == 1) ? true : false;
1669}
1670
1671bool ModePolicy::getContentTypeSupport(const char* type) {
1672 char content_type_cap[MESON_MAX_STR_LEN] = {0};
1673 sysfs_get_string(HDMI_CONTENT_TYPE_CAP, content_type_cap, MESON_MAX_STR_LEN);
1674 if (strstr(content_type_cap, type)) {
1675 MESON_LOGI("getContentTypeSupport: %s is true", type);
1676 return true;
1677 }
1678
1679 MESON_LOGI("getContentTypeSupport: %s is false", type);
1680 return false;
1681}
1682
1683bool ModePolicy::getGameContentTypeSupport() {
1684 return getContentTypeSupport(CONTENT_TYPE_CAP[3]);
1685}
1686
1687bool ModePolicy::getSupportALLMContentTypeList(std::vector<std::string> *supportModes) {
1688 if (isTvSupportALLM()) {
1689 (*supportModes).push_back(std::string("allm"));
1690 }
1691
1692 for (int i = 0; i < ARRAY_SIZE(CONTENT_TYPE_CAP); i++) {
1693 if (getContentTypeSupport(CONTENT_TYPE_CAP[i])) {
1694 (*supportModes).push_back(std::string(CONTENT_TYPE_CAP[i]));
1695 }
1696 }
1697
1698 return true;
1699}
1700
1701
1702void ModePolicy::setTvDVEnable() {
1703 //if TV
1704 setHdrMode(HDR_MODE_OFF);
1705 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FOLLOW_SINK);
1706
1707 usleep(100000);//100ms
1708 setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_ENABLE);
1709 usleep(100000);//100ms
1710
1711 setHdrMode(HDR_MODE_AUTO);
1712
1713 initGraphicsPriority();
1714}
1715
1716void ModePolicy::setTvDVDisable() {
1717 int check_status_count = 0;
1718
1719 //2. update sysfs
1720 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
1721
1722 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE);
1723 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_MODE_BYPASS);
1724 usleep(100000);//100ms
1725 std::string dvstatus = "";
1726 getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus);
1727
1728 if (strcmp(dvstatus.c_str(), BYPASS_PROCESS)) {
1729 while (++check_status_count <30) {
1730 usleep(20000);//20ms
1731 getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus);
1732 if (!strcmp(dvstatus.c_str(), BYPASS_PROCESS)) {
1733 break;
1734 }
1735 }
1736 }
1737
1738 MESON_LOGI("dvstatus %s, check_status_count [%d]", dvstatus.c_str(), check_status_count);
1739 setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_DISABLE);
1740
1741 setHdrMode(HDR_MODE_AUTO);
1742 setSdrMode(SDR_MODE_AUTO);
1743}
1744
1745
1746int32_t ModePolicy::setDvMode(std::string &amdv_mode) {
1747 MESON_LOGI("%s dv mode:%s", __FUNCTION__, amdv_mode.c_str());
1748
1749 if (DISPLAY_TYPE_TV == mDisplayType) {
1750 //1. update prop
1751 strcpy(mConData.hdr_info.ubootenv_dv_type, amdv_mode.c_str());
1752
1753 //2. apply to driver
1754 if (strstr(amdv_mode.c_str(), "0")) {
1755 strcpy(mDvInfo.amdv_enable, "0");
1756 setTvDVDisable();
1757 } else {
1758 strcpy(mDvInfo.amdv_enable, "1");
1759 setTvDVEnable();
1760 }
1761
1762 //3. save env
1763 setBootEnv(UBOOTENV_DV_ENABLE, mDvInfo.amdv_enable);
1764 } else {
1765 //1. update dv env
1766 strcpy(mConData.hdr_info.ubootenv_dv_type, amdv_mode.c_str());
1767
1768 if (strstr(amdv_mode.c_str(), "0")) {
1769 strcpy(mDvInfo.amdv_enable, "0");
1770 } else {
1771 strcpy(mDvInfo.amdv_enable, "1");
1772 }
1773
1774 //Save user prefer dv mode only user change dv through UI
1775 setBootEnv(UBOOTENV_USER_DV_TYPE, mConData.hdr_info.ubootenv_dv_type);
1776 setBootEnv(UBOOTENV_DV_ENABLE, mDvInfo.amdv_enable);
1777 setBootEnv(UBOOTENV_DOLBYSTATUS, amdv_mode.c_str());
1778
1779 //2. set hdmi mode for trigger setting
1780 setSourceOutputMode(mCurrentMode);
1781 }
1782
1783 return 0;
1784}
1785
1786
1787/* *
1788 * @Description: this is a temporary solution, should be revert when android.hardware.graphics.composer@2.4 finished
1789 * set the ALLM_Mode
1790 * @params: "0": ALLM disable (VSIF still contain allm info)
1791 * "1": ALLM enable
1792 * "-1":really disable ALLM (VSIF don't contain allm info)
1793 * */
1794void ModePolicy::setALLMMode(int state) {
1795 /***************************************************************
1796 * Comment for special solution in this func *
1797 ***************************************************************
1798 * *
1799 * In HDMI Standard only 0 to disable ALLM and 1 to enable ALLM*
1800 * but ALLM and DV share the same bit in VSIF *
1801 * it cause conflict *
1802 * *
1803 * So in amlogic special solution: *
1804 * we add -1 to *
1805 * 1: disable ALLM *
1806 * 2: clean ALLM info in VSIF conflict bit *
1807 * when user set 0 to ALLM *
1808 * we will force change 0 into -1 here *
1809 * *
1810 ***************************************************************/
1811
1812 if (!isTvSupportALLM()) {
1813 SYS_LOGI("setALLMMode: TV not support ALLM\n");
1814 return;
1815 }
1816
1817 int perState = -1;
1818 char cur_allm_state[MESON_MODE_LEN] = {0};
1819 sysfs_get_string(AUTO_LOW_LATENCY_MODE, cur_allm_state, MESON_MODE_LEN);
1820 perState = atoi(cur_allm_state);
1821 if (perState == state) {
1822 SYS_LOGI("setALLMMode: the ALLM_Mode is not changed :%d\n", state);
1823 return;
1824 }
1825
1826 bool isTVSupportDV = isTvSupportDV();
1827
1828 char ubootenv_amdv_enable[MESON_MODE_LEN] = {0};
1829 std::string cur_ColorAttribute;
1830 char ubootenv_amdv_type[MESON_MODE_LEN] = {0};
1831 bool ret = false;
1832
1833 switch (state) {
1834 case -1:
1835 [[fallthrough]];
1836 case 0:
1837 //1. disable allm
1838 sysfs_set_string(AUTO_LOW_LATENCY_MODE, ALLM_MODE[0]);
1839 MESON_LOGI("setALLMMode: ALLM_Mode: %s", ALLM_MODE[0]);
1840 //2.1 get dv status before enable allm
1841 getBootEnv(UBOOTENV_DV_ENABLE, ubootenv_amdv_enable);
1842 //2.2 get current hdmi output resolution
1843 getDisplayMode(mCurrentMode);
1844 //2.3 get current hdmi output color space
1845 getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute);
1846 //2.4 get dv type before enable allm
1847 ret = getBootEnv(UBOOTENV_USER_DV_TYPE, ubootenv_amdv_type);
1848 //3 enable dv
1849 //when TV and current resolution support dv and dv is enable before enable allm
1850 if (isTVSupportDV
1851 && !strcmp(ubootenv_amdv_enable, "1")
1852 && !(meson_mode_support_mode(mModeConType, MESON_DOLBY_VISION_PRIORITY, mCurrentMode))) {
1853 // restore doblyvision when set -1/0 to ALLM
1854 if (!ret) {
1855 //best dv policy:sink-led -->source led
1856 if (strstr(mConData.hdr_info.dv_deepcolor, "DV_RGB_444_8BIT") != NULL
1857 && strstr(cur_ColorAttribute.c_str(), "444,8bit") != NULL) {
1858 enableDV(AMDV_SET_ENABLE);
leng.fangd8ab2872024-06-28 16:23:43 +08001859 mSceneOutInfo.amdv_type = AMDV_SET_ENABLE;
leng.fang91856072024-06-07 14:12:54 +08001860 } else if (strstr(mConData.hdr_info.dv_deepcolor, "LL_YCbCr_422_12BIT") != NULL
1861 && strstr(cur_ColorAttribute.c_str(), "422,12bit") != NULL) {
1862 enableDV(AMDV_SET_ENABLE_LL_YUV);
leng.fangd8ab2872024-06-28 16:23:43 +08001863 mSceneOutInfo.amdv_type = AMDV_SET_ENABLE_LL_YUV;
leng.fang91856072024-06-07 14:12:54 +08001864 } else {
1865 SYS_LOGI("can't enable dv for dv_deepcolor: %s and curColorAttribute: %s\n",
1866 mConData.hdr_info.dv_deepcolor, cur_ColorAttribute.c_str());
1867 }
1868 } else if (!strcmp(ubootenv_amdv_type, "2") && strstr(cur_ColorAttribute.c_str(), "422,12bit") != NULL) {
1869 enableDV(AMDV_SET_ENABLE_LL_YUV);
leng.fangd8ab2872024-06-28 16:23:43 +08001870 mSceneOutInfo.amdv_type = AMDV_SET_ENABLE_LL_YUV;
leng.fang91856072024-06-07 14:12:54 +08001871 } else if (!strcmp(ubootenv_amdv_type, "1") && strstr(cur_ColorAttribute.c_str(), "444,8bit") != NULL) {
1872 enableDV(AMDV_SET_ENABLE);
leng.fangd8ab2872024-06-28 16:23:43 +08001873 mSceneOutInfo.amdv_type = AMDV_SET_ENABLE;
leng.fang91856072024-06-07 14:12:54 +08001874 } else {
1875 SYS_LOGI("can't enable dv for curColorAttribute: %s\n", cur_ColorAttribute.c_str());
1876 }
1877 }
1878 break;
1879 case 1:
1880 //when TV support dv and dv is enable
1881 if (isTVSupportDV && isDVEnable()) {
leng.fangd8ab2872024-06-28 16:23:43 +08001882 mSceneOutInfo.amdv_type = AMDV_SET_DISABLE;
leng.fang91856072024-06-07 14:12:54 +08001883 // disable the doblyvision when ALLM enable
1884 disableDV(AMDV_SET_DISABLE);
1885 }
1886 //2. enable allm
1887 sysfs_set_string(AUTO_LOW_LATENCY_MODE, ALLM_MODE[2]);
1888 MESON_LOGI("setALLMMode: ALLM_Mode: %s", ALLM_MODE[2]);
1889 break;
1890 default:
1891 MESON_LOGE("setALLMMode: ALLM_Mode: error state[%d]", state);
1892 break;
1893 }
1894}
1895
1896bool ModePolicy::isTvConnector() {
1897 auto type = mConnector->connector_type;
1898 if (type == DRM_MODE_CONNECTOR_MESON_LVDS_A || type == DRM_MODE_CONNECTOR_MESON_LVDS_B ||
1899 type == DRM_MODE_CONNECTOR_MESON_LVDS_C || type == DRM_MODE_CONNECTOR_MESON_VBYONE_A ||
1900 type == DRM_MODE_CONNECTOR_MESON_VBYONE_B || type == DRM_MODE_CONNECTOR_LVDS ||
1901 type == LEGACY_NON_DRM_CONNECTOR_PANEL)
1902 return true;
1903
1904 return false;
1905}
1906
1907int32_t ModePolicy::setAutoLowLatencyMode(bool enabled) {
1908 auto type = mConnector->connector_type;
1909 if (type == DRM_MODE_CONNECTOR_HDMIA) {
1910 if (!isTvSupportALLM()) {
1911 return -1;
1912 }
1913
1914 if (enabled) {
1915 sysfs_set_string(LOW_LATENCY, LOW_LATENCY_ENABLE);
1916 } else {
1917 sysfs_set_string(LOW_LATENCY, LOW_LATENCY_DISABLE);
1918 }
1919 setALLMMode(enabled);
1920 return 0;
1921 }
1922
1923 // do nothing for tv
1924 if (isTvConnector())
1925 return 0;
1926
1927 return -1;
1928}
1929
1930void ModePolicy::setAllowedHdrTypes(uint32_t allowedHdrTypes, bool isAuto, bool passThrough) {
1931 //Match content Dynamic range
1932 if (passThrough) {
1933 setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_MATCH_CONTENT]);
1934 }
1935 // force SDR when autoAllowedHdrTypes are empty on system-preferred conversion
1936 else if (allowedHdrTypes == 0 && isAuto) {
1937 uint32_t userHdrType = 0;
1938 userHdrType = userHdrType | (1 << HAL_HDR_AMDV);
1939 userHdrType = userHdrType | (1 << HAL_HDR_HDR10);
1940 userHdrType = userHdrType | (1 << HAL_HDR_HLG);
1941 userHdrType = userHdrType | (1 << DRM_INVALID);
1942 string keyValue = std::to_string(userHdrType);
1943 setBootEnv(UBOOTENV_USER_PREFERRED_HDR_TYPE, keyValue.c_str());
1944 setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_SYSTEM_PREFERRED]);
1945 return;
1946 } else {
1947 //bit0-bit4 for hdr type and 1 is disable 0 is enable
1948 uint32_t userHdrType = 0;
1949 userHdrType = userHdrType | (1 << HAL_HDR_AMDV);
1950 userHdrType = userHdrType | (1 << HAL_HDR_HDR10);
1951 userHdrType = userHdrType | (1 << HAL_HDR_HLG);
1952 userHdrType = userHdrType | (1 << DRM_INVALID);
1953 allowedHdrTypes ^= userHdrType;
1954 allowedHdrTypes &= userHdrType;
1955 string keyValue = std::to_string(allowedHdrTypes);
1956 setBootEnv(UBOOTENV_USER_PREFERRED_HDR_TYPE, keyValue.c_str());
1957 if (isAuto)
1958 setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_SYSTEM_PREFERRED]);
1959 else
1960 setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_FORCE]);
1961
1962 MESON_LOGD("%s AllowedHdrType %d isAuto %d keyValue %s \n", __func__, allowedHdrTypes, isAuto, keyValue.c_str());
1963 }
1964
1965 return;
1966}
1967
1968int32_t ModePolicy::getPreferredHdrConversionType(void) {
1969 int32_t outHdrConversionType = -1;
1970
1971 char auto_policy[MESON_MODE_LEN] = {0};
1972 memset(auto_policy, 0, MESON_MODE_LEN);
1973 getBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, auto_policy);
1974
1975 //Match content Dynamic range
1976 if (strstr(auto_policy, MESON_HDR_PREFERRED_POLICY[MESON_HDR_MATCH_CONTENT])) {
1977 mHdr_policy = MESON_HDR_POLICY_SOURCE;
1978 mHdr_priority = MESON_G_DV_HDR10_HLG;
1979 }
1980 //System-preferred conversion or Force conversion
1981 else {
1982 bool isAuto = true;
1983 if (strstr(auto_policy, MESON_HDR_PREFERRED_POLICY[MESON_HDR_FORCE])) {
1984 isAuto = false;
1985 }
1986
1987 char user_hdr_type[MESON_MODE_LEN] = {0};
1988 memset(user_hdr_type, 0, MESON_MODE_LEN);
1989 bool ret = getBootEnv(UBOOTENV_USER_PREFERRED_HDR_TYPE, user_hdr_type);
1990 int32_t allowedHdrType = atoi(user_hdr_type);
1991 if (ret) {
1992 allowedHdrType = atoi(user_hdr_type);
1993 } else {
1994 allowedHdrType = 0; //all hdr enable as default
1995 }
1996
1997 //force SDR when autoAllowedHdrTypes are empty on system-preferred conversion
1998 uint32_t userHdrType = 0;
1999 userHdrType = userHdrType | (1 << HAL_HDR_AMDV);
2000 userHdrType = userHdrType | (1 << HAL_HDR_HDR10);
2001 userHdrType = userHdrType | (1 << HAL_HDR_HLG);
2002 userHdrType = userHdrType | (1 << DRM_INVALID);
2003 string keyValue = std::to_string(userHdrType);
2004 if (isAuto && strstr (user_hdr_type, keyValue.c_str())) {
2005 mHdr_priority = MESON_G_SDR;
2006 outHdrConversionType = DRM_INVALID;
2007 } else {
2008 bool containDVType = false, containHDR10Type = false,
2009 containHLGType = false, containSDRType = false;
2010
2011 MESON_LOGD("allowedHdrType 0x%x ", allowedHdrType);
2012 if (!(allowedHdrType & (1 << HAL_HDR_AMDV)))
2013 containDVType = true;
2014 if (!(allowedHdrType & (1 << HAL_HDR_HDR10)))
2015 containHDR10Type = true;
2016 if (!(allowedHdrType & (1 << HAL_HDR_HLG)))
2017 containHLGType = true;
2018 if (!(allowedHdrType & (1 << DRM_INVALID)))
2019 containSDRType = true;
2020
2021 drm_hdr_capabilities hdrCaps;
2022 getHdrCapabilities(&hdrCaps);
2023
2024 if (isAuto) {
2025 if (hdrCaps.DVSupported) {
2026 if (containHLGType && containHDR10Type && containDVType) {
2027 mHdr_policy = MESON_HDR_POLICY_SINK;
2028 mHdr_priority = MESON_G_DV_HDR10_HLG;
2029 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2030 } else if (containHDR10Type && containDVType) {
2031 mHdr_policy = MESON_HDR_POLICY_SINK;
2032 mHdr_priority = MESON_G_DV_HDR10;
2033 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2034 } else if (containHLGType && containDVType) {
2035 mHdr_policy = MESON_HDR_POLICY_SINK;
2036 mHdr_priority = MESON_G_DV_HLG;
2037 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2038 } else if (containHLGType && containHDR10Type) {
2039 mHdr_policy = MESON_HDR_POLICY_SINK;
2040 mHdr_priority = MESON_G_HDR10_HLG;
2041 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10);
2042 } else if (containDVType) {
2043 mHdr_policy = MESON_HDR_POLICY_SINK;
2044 mHdr_priority = MESON_G_DV;
2045 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2046 } else if (containHDR10Type) {
2047 mHdr_policy = MESON_HDR_POLICY_SINK;
2048 mHdr_priority = MESON_G_HDR10;
2049 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10);
2050 } else if (containHLGType) {
2051 mHdr_priority = MESON_G_HLG;
2052 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source due to dv can't HLG output
2053 } else {
2054 mHdr_policy = MESON_HDR_POLICY_SINK;
2055 mHdr_priority = MESON_G_SDR;
2056 outHdrConversionType = DRM_INVALID; //force sdr
2057 }
2058 } else {
2059 if (containHLGType && containHDR10Type) {
2060 mHdr_policy = MESON_HDR_POLICY_SINK;
2061 mHdr_priority = MESON_G_HDR10_HLG;
2062 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10);
2063 } else if (containHDR10Type) {
2064 mHdr_policy = MESON_HDR_POLICY_SINK;
2065 mHdr_priority = MESON_G_HDR10;
2066 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10);
2067 } else if (containHLGType) {
2068 mHdr_policy = MESON_HDR_POLICY_SINK;
2069 mHdr_priority = MESON_G_HLG;
2070 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HLG);
2071 } else {
2072 mHdr_policy = MESON_HDR_POLICY_SINK;
2073 mHdr_priority = MESON_G_SDR;
2074 outHdrConversionType = DRM_INVALID; //force sdr
2075 }
2076 }
2077 } else {
2078 if (containDVType) {
2079 if (hdrCaps.DVSupported) {
2080 mHdr_policy = MESON_HDR_POLICY_SINK;
2081 mHdr_priority = MESON_G_DV;
2082 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2083 } else {
2084 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source
2085 mHdr_priority = MESON_G_DV_HDR10_HLG;
2086 }
2087 } else if (containHDR10Type) {
2088 if (hdrCaps.HDR10Supported) {
2089 mHdr_policy = MESON_HDR_POLICY_SINK;
2090 mHdr_priority = MESON_G_HDR10;
2091 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10);
2092 } else {
2093 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source
2094 mHdr_priority = MESON_G_DV_HDR10_HLG;
2095 }
2096 } else if (containHLGType) {
2097 if (hdrCaps.HLGSupported) {
2098 if (hdrCaps.DVSupported) {
2099 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source due to dv can't HLG output
2100 mHdr_priority = MESON_G_DV_HDR10_HLG;
2101 } else {
2102 mHdr_policy = MESON_HDR_POLICY_SINK;
2103 mHdr_priority = MESON_G_HLG;
2104 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HLG);
2105 }
2106 } else {
2107 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source
2108 mHdr_priority = MESON_G_DV_HDR10_HLG;
2109 }
2110 } else {
2111 mHdr_policy = MESON_HDR_POLICY_SINK;
2112 mHdr_priority = MESON_G_SDR;
2113 outHdrConversionType = DRM_INVALID; //force sdr
2114 }
2115 }
2116 }
2117 }
2118
2119 MESON_LOGD("hdr_policy:%d hdr_priority:0x%x outHdrConversionType:%d ", mHdr_policy, mHdr_priority, outHdrConversionType);
2120 return outHdrConversionType;
2121}
2122
2123int32_t ModePolicy::setHdrConversionPolicy(bool passthrough, int32_t forceType) {
2124 int32_t ret = 0;
2125 MESON_LOGD("%s passthrough %d forceType %d",
2126 __func__, passthrough, forceType);
2127
2128 if (passthrough || (forceType == -1)) {
2129 setBootEnv(UBOOTENV_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
2130
2131 char hdr_priority[MESON_MODE_LEN] = {0};
2132 sprintf(hdr_priority, "%d", mHdr_priority);
2133 setBootEnv(UBOOTENV_HDR_PRIORITY, hdr_priority);
2134 // set current hdmi mode
2135 getDisplayMode(mCurrentMode);
2136 setSourceOutputMode(mCurrentMode);
2137 } else {
2138 std::string type = FORCE_AMDV;
2139 meson_hdr_priority_e priority = MESON_DOLBY_VISION_PRIORITY;
2140 switch (forceType) {
2141 case DRM_AMDV: {
2142 priority = MESON_DOLBY_VISION_PRIORITY;
2143 type = FORCE_AMDV;
2144 break;
2145 }
2146 case DRM_HDR10:{
2147 priority = MESON_HDR10_PRIORITY;
2148 type = FORCE_HDR10;
2149 break;
2150 }
2151 case DRM_HLG:{
2152 priority = MESON_HDR10_PRIORITY;
2153 type = FORCE_HLG;
2154 break;
2155 }
2156 case DRM_INVALID: {
2157 priority = MESON_SDR_PRIORITY;
2158 type = AMDV_DISABLE_FORCE_SDR;
2159 break;
2160 }
2161 default:
2162 MESON_LOGE("setHdrConversionStrategy: error type[%d]", forceType);
2163 ret = -1;
2164 break;
2165 }
2166
2167 if (!ret) {
2168 getDisplayMode(mCurrentMode);
2169 meson_mode_set_policy_input(mModeConType, &mConData);
2170 if (!meson_mode_support_mode(mModeConType, priority, mCurrentMode)) {
2171 char hdr_policy[MESON_MODE_LEN] = {0};
2172 sprintf(hdr_policy, "%d", mHdr_policy);
2173 setBootEnv(UBOOTENV_HDR_POLICY, hdr_policy);
2174
2175 char hdr_priority[MESON_MODE_LEN] = {0};
2176 sprintf(hdr_priority, "%d", mHdr_priority);
2177 setBootEnv(UBOOTENV_HDR_PRIORITY, hdr_priority);
2178
2179 setSourceOutputMode(mCurrentMode);
2180 } else {
2181 MESON_LOGW("%s mode check failed\n", __func__);
2182 ret = -EINVAL;
2183 }
2184 }
2185 }
2186
2187 return ret;
2188}
2189
2190/*
2191* apply setting
2192*/
2193void ModePolicy::applyDisplaySetting(bool force) {
2194 //quiescent boot need not output
2195 bool quiescent = sys_get_bool_prop("ro_boot_quiescent", false);
2196
2197 MESON_LOGI("quiescent_mode is %d\n", quiescent);
2198 if (quiescent && (mState == OUTPUT_MODE_STATE_INIT)) {
2199 MESON_LOGI("don't need to setting hdmi when quiescent mode\n");
2200 return;
2201 }
2202
2203 //check cvbs mode
2204 bool cvbsMode = false;
2205
2206 if (!strcmp(mSceneOutInfo.displaymode, MODE_480CVBS) || !strcmp(mSceneOutInfo.displaymode, MODE_576CVBS)
2207 || !strcmp(mSceneOutInfo.displaymode, MODE_PAL_M) || !strcmp(mSceneOutInfo.displaymode, MODE_PAL_N)
2208 || !strcmp(mSceneOutInfo.displaymode, MODE_NTSC_M)
2209 || !strcmp(mSceneOutInfo.displaymode, "null") || !strcmp(mSceneOutInfo.displaymode, "dummy_l")
2210 || !strcmp(mSceneOutInfo.displaymode, MODE_PANEL)) {
2211 cvbsMode = true;
2212 }
2213
2214 /* not enable phy in systemcontrol by default
2215 * as phy will be enabled in driver when set mode
2216 * only enable phy if phy is disabled but not enabled
2217 */
2218 bool phy_enabled_already = true;
2219
2220 // 1. update hdmi frac_rate_policy
2221 char frac_rate_policy[MESON_MODE_LEN] = {0};
2222 char cur_frac_rate_policy[MESON_MODE_LEN] = {0};
2223 bool frac_rate_policy_change = false;
2224 std::string policy;
2225
2226 if (mReason != OUTPUT_CHANGE_BY_HWC) {
2227 getDisplayAttribute(DISPLAY_FRAC_RATE_POLICY, policy);
2228 strcpy(cur_frac_rate_policy, policy.c_str());
2229 getBootEnv(UBOOTENV_FRAC_RATE_POLICY, frac_rate_policy);
2230 if (strstr(frac_rate_policy, cur_frac_rate_policy) == NULL) {
2231 setDisplayAttribute(DISPLAY_FRAC_RATE_POLICY, frac_rate_policy);
2232 frac_rate_policy_change = true;
2233 } else {
2234 MESON_LOGI("cur frac_rate_policy is equals\n");
2235 }
2236 } else {
2237 getDisplayAttribute(DISPLAY_FRAC_RATE_POLICY, policy);
2238 strcpy(cur_frac_rate_policy, policy.c_str());
2239 char defVal[] = "2";
2240 sys_get_string_prop_default(HDMI_FRC_POLICY_PROP,frac_rate_policy, defVal);
2241 if (strstr(frac_rate_policy,"2")) {
2242 getBootEnv(UBOOTENV_FRAC_RATE_POLICY, frac_rate_policy);
2243 }
2244 MESON_LOGI("get frc policy from hwc is %s and current value is %s\n",frac_rate_policy, cur_frac_rate_policy);
2245 if (strstr(frac_rate_policy, cur_frac_rate_policy) == NULL) {
2246 frac_rate_policy_change = true;
2247 }
2248 }
2249
2250 // 2. set hdmi final color space
2251 char curColorAttribute[MESON_MODE_LEN] = {0};
2252 char final_deepcolor[MESON_MODE_LEN] = {0};
2253 bool attr_change = false;
2254
2255 std::string cur_ColorAttribute;
2256 getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute);
2257 strcpy(curColorAttribute, cur_ColorAttribute.c_str());
2258 strcpy(final_deepcolor, mSceneOutInfo.deepcolor);
2259 MESON_LOGI("curDeepcolor[%s] final_deepcolor[%s]\n", curColorAttribute, final_deepcolor);
2260
2261 if (strstr(curColorAttribute, final_deepcolor) == NULL) {
2262 MESON_LOGI("set color space from:%s to %s\n", curColorAttribute, final_deepcolor);
2263 // setDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, final_deepcolor);
2264 cur_ColorAttribute = final_deepcolor;
2265 attr_change = true;
2266 } else {
2267 MESON_LOGI("cur deepcolor is equals\n");
2268 }
2269
2270 // 3. update hdr strategy
2271 bool hdr_policy_change = false;
2272 std::string cur_hdr_policy;
2273 getDisplayAttribute(DISPLAY_HDR_POLICY, cur_hdr_policy);
2274 MESON_LOGI("cur hdr policy:%s\n", cur_hdr_policy.c_str());
2275
2276 std::string cur_hdr_force_mode;
2277 getDisplayAttribute(DISPLAY_FORCE_HDR_MODE, cur_hdr_force_mode);
2278 MESON_LOGI("cur hdr force mode:%s\n", cur_hdr_force_mode.c_str());
2279
2280 std::string cur_amdv_mode;
2281 getDisplayAttribute(DISPLAY_AMDV_MODE, cur_amdv_mode);
2282 MESON_LOGI("cur dv mode:%s\n", cur_amdv_mode.c_str());
2283
2284 std::string cur_amdv_policy;
2285 getDisplayAttribute(DISPLAY_AMDV_POLICY, cur_amdv_policy);
2286 MESON_LOGI("cur dv policy:%s\n", cur_amdv_policy.c_str());
2287
2288 char hdr_force_mode[MESON_MODE_LEN] = {0};
2289 gethdrforcemode(hdr_force_mode);
2290
2291 char hdr_policy[MESON_MODE_LEN] = {0};
2292 getHdrStrategy(hdr_policy);
2293
2294 if (!isDVEnable()) {
2295 if (strstr(cur_hdr_policy.c_str(), hdr_policy) == NULL) {
2296 MESON_LOGI("set hdr policy from:%s to %s\n", cur_hdr_policy.c_str(), hdr_policy);
2297 hdr_policy_change = true;
2298 } else if (!strcmp(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]) && (strstr(cur_hdr_force_mode.c_str(), hdr_force_mode) == NULL)) {
2299 MESON_LOGI("set hdr force mode from:%s to %s\n", cur_hdr_force_mode.c_str(), hdr_force_mode);
2300 hdr_policy_change = true;
2301 }
2302 } else {
2303 if (strstr(cur_amdv_policy.c_str(), hdr_policy) == NULL) {
2304 MESON_LOGI("set dv policy from:%s to %s\n", cur_amdv_policy.c_str(), hdr_policy);
2305 hdr_policy_change = true;
leng.fangd8ab2872024-06-28 16:23:43 +08002306 } else if ((mSceneOutInfo.amdv_type != AMDV_SET_DISABLE)
leng.fang91856072024-06-07 14:12:54 +08002307 && (!strcmp(hdr_policy, AMDV_POLICY_FORCE_MODE)
2308 && (strstr(cur_amdv_mode.c_str(), hdr_force_mode) == NULL))) {
2309 MESON_LOGI("set dv force mode from:%s to %s\n", cur_amdv_mode.c_str(), hdr_force_mode);
2310 hdr_policy_change = true;
2311 }
2312 }
2313
2314 //update hdr priority
2315 bool hdr_priority_change = false;
2316 meson_hdr_priority_e cur_hdr_priority;
2317 cur_hdr_priority = (meson_hdr_priority_e)getCurrentHdrPriority();
2318
2319 meson_hdr_priority_e hdr_priority;
2320 hdr_priority = (meson_hdr_priority_e)getHdrPriority();
2321
2322 if (cur_hdr_priority != hdr_priority) {
2323 SYS_LOGI("set hdr priority from:%x to %x\n", cur_hdr_priority, hdr_priority);
2324 hdr_priority_change = true;
2325 }
2326
2327 // 4. check dv
2328 int amdv_type = AMDV_SET_DISABLE;
2329 bool amdv_change = false;
2330
leng.fangd8ab2872024-06-28 16:23:43 +08002331 amdv_type = mSceneOutInfo.amdv_type;
leng.fang91856072024-06-07 14:12:54 +08002332 amdv_change = checkDVStatusChanged(amdv_type);
2333 if (isMboxSupportDV() && amdv_change && (hdr_priority == MESON_DOLBY_VISION_PRIORITY)) {
2334 //4.1 set avmute when signal change at boot
2335 if ((OUTPUT_MODE_STATE_INIT == mState)
2336 && (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]))) {
2337 // setDisplayAttribute(DISPLAY_HDMI_AVMUTE, "1");
2338 }
2339 //4.2 set dummy_l mode when dv change at UI switch
2340 if ((OUTPUT_MODE_STATE_SWITCH == mState) && amdv_change) {
2341 setDisplayMode("dummy_l");
2342 }
2343 //4.3 enable or disable dv core
2344 if (AMDV_SET_DISABLE != amdv_type) {
2345 enableDV(amdv_type);
2346 } else {
2347 disableDV(amdv_type);
2348 }
2349
2350 MESON_LOGI("isDVEnable: %d", isDVEnable());
2351 } else {
2352 amdv_change = false;
2353 MESON_LOGI("cur DvMode is equals\n");
2354 }
2355
2356 // 5. check hdmi output mode
2357 char final_displaymode[MESON_MODE_LEN] = {0};
2358 char curDisplayMode[MESON_MODE_LEN] = {0};
2359 bool modeChange = false;
2360
2361 getDisplayMode(curDisplayMode);
2362 strcpy(final_displaymode, mSceneOutInfo.displaymode);
2363 MESON_LOGI("curMode:[%s] ,final_displaymode[%s]\n", curDisplayMode, final_displaymode);
2364
2365 if (!isMatchMode(curDisplayMode, final_displaymode)) {
2366 modeChange = true;
2367 } else {
2368 MESON_LOGI("cur mode is equals\n");
2369 }
2370
2371 //6. check any change
2372 bool isNeedChange = false;
2373
2374 if (amdv_change || modeChange || attr_change || frac_rate_policy_change || hdr_policy_change || hdr_priority_change) {
2375 isNeedChange = true;
2376 } else if (force) {
2377 isNeedChange = true;
2378 MESON_LOGD("force changed");
2379 } else {
2380 MESON_LOGI("nothing need to be changed\n");
2381 }
2382
2383 // 8. set hdmi final output mode
2384 if (isNeedChange) {
2385 //apply hdr policy to driver sysfs
2386 if (hdr_policy_change) {
2387 if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) {
2388 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
2389 if (isDVEnable()) {
2390 setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
2391 }
2392 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) {
2393 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
2394 if (isDVEnable()) {
2395 setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
2396 }
2397 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]) || strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) {
2398 char hdr_force_mode[MESON_MODE_LEN] = {0};
2399 gethdrforcemode(hdr_force_mode);
2400 setDisplayAttribute(DISPLAY_FORCE_HDR_MODE, hdr_force_mode);
2401 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]);
2402 if (isDVEnable()) {
2403 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE);
2404 if (strstr(hdr_force_mode, FORCE_AMDV)) {
2405 setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_AMDV);
2406 } else if (strstr(hdr_force_mode, FORCE_HDR10)) {
2407 setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_HDR10);
2408 } else if (strstr(hdr_force_mode, AMDV_DISABLE_FORCE_SDR)) {
2409 // 8bit or not
2410 // std::string cur_ColorAttribute;
2411 // getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute);
2412 if (cur_ColorAttribute.find("8bit", 0) != std::string::npos) {
2413 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_8BIT);
2414 } else {
2415 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_10BIT);
2416 }
2417 }
2418 }
2419 }
2420 }
2421
leng.fang9cf09e22024-07-17 20:01:11 +08002422 if (attr_change || modeChange || frac_rate_policy_change || force)
leng.fang91856072024-06-07 14:12:54 +08002423 mAdapter->setColorAttribute(final_deepcolor);
2424
2425 //apply hdr priority to driver sysfs
2426 if (hdr_priority_change) {
2427 char tmp[MESON_MODE_LEN] = {0};
2428 sprintf(tmp, "%d", hdr_priority);
2429 setDisplayAttribute(DISPLAY_HDR_PRIORITY, tmp);
2430 }
2431
2432 //set hdmi mode
2433 setDisplayMode(final_displaymode);
2434 /* phy already turned on after write display/mode node */
2435 phy_enabled_already = true;
2436 } else {
2437 MESON_LOGI("curDisplayMode is equal final_displaymode, Do not need set it\n");
2438 }
2439
2440 // graphic
2441 char final_Mode[MESON_MODE_LEN] = {0};
2442 getDisplayMode(final_Mode);
2443 char defVal[] = "0x0";
2444 if (sys_get_bool_prop(PROP_DISPLAY_SIZE_CHECK, true)) {
2445 char resolution[MESON_MODE_LEN] = {0};
2446 char defaultResolution[MESON_MODE_LEN] = {0};
2447 char finalResolution[MESON_MODE_LEN] = {0};
2448 int w = 0, h = 0, w1 =0, h1 = 0;
2449 sysfs_get_string(SYS_DISPLAY_RESOLUTION, resolution, MESON_MODE_LEN);
2450 sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal);
2451 sscanf(resolution, "%dx%d", &w, &h);
2452 sscanf(defaultResolution, "%dx%d", &w1, &h1);
2453 if ((w != w1) || (h != h1)) {
2454 if (strstr(final_displaymode, "null") && w1 != 0) {
2455 sprintf(finalResolution, "%dx%d", w1, h1);
2456 } else {
2457 sprintf(finalResolution, "%dx%d", w, h);
2458 }
2459 sys_set_prop(PROP_DISPLAY_SIZE, finalResolution);
2460 }
2461 }
2462 sys_set_prop(PROP_DISPLAY_ALLM, isTvSupportALLM() ? "1" : "0");
2463 sys_set_prop(PROP_DISPLAY_GAME, getGameContentTypeSupport() ? "1" : "0");
2464
2465 char defaultResolution[MESON_MODE_LEN] = {0};
2466 sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal);
2467 MESON_LOGI("set display-size:%s\n", defaultResolution);
2468
2469 int position[4] = { 0, 0, 0, 0 };//x,y,w,h
2470 getPosition(final_displaymode, position);
2471 setPosition(final_displaymode, position[0], position[1],position[2], position[3]);
2472
2473 //audio
2474 char value[MESON_MAX_STR_LEN] = {0};
2475 memset(value, 0, sizeof(0));
2476 getBootEnv(UBOOTENV_DIGITAUDIO, value);
2477 setDigitalMode(value);
2478}
2479
2480void ModePolicy::getFramebufferSize(int disp, uint32_t & width, uint32_t & height) {
2481 char uiMode[PROPERTY_VALUE_MAX] = {0};
2482 if (disp == 0) {
2483 /*primary display*/
2484 if (sys_get_string_prop_default("persist_vendor_hwc_ui_mode", uiMode, "1080") > 0) {
2485 if (!strncmp(uiMode, "720", 3)) {
2486 width = 1280;
2487 height = 720;
2488 } else if (!strncmp(uiMode, "1080", 4)) {
2489 width = 1920;
2490 height = 1080;
2491 } else {
2492 MESON_ASSERT(0, "%s: get not support mode [%s] from vendor.ui_mode",
2493 __func__, uiMode);
2494 }
2495 } else {
2496 width = 1920;
2497 height = 1080;
2498 }
2499 }
2500}
2501
2502int32_t ModePolicy::initialize() {
2503 uint32_t width = 1280;
2504 uint32_t height = 1080;
2505 char log_level[PROPERTY_VALUE_MAX] = { 0 };
2506
leng.fang3e8a4b52024-07-24 14:51:30 +08002507 sys_get_string_prop_default("WESTON_GL_MODE_POLICY_DEBUG", log_level, "2");
leng.fang91856072024-06-07 14:12:54 +08002508 g_activeLevel = atoi(log_level);
2509 mAdapter->setLogLevel(g_activeLevel);
2510
2511 bootenv_init();
2512 getFramebufferSize(mDisplayId, width, height);
2513 mDefaultUI = to_string(height);
2514
2515 mAdapter->initDisplayAttributeInfo(mCrtc, mConnector);
2516 updateHdrCaps();
2517 if (DISPLAY_TYPE_MBOX == mDisplayType) {
2518 // mTxAuth = std::make_shared<HDCPTxAuth>();
2519
2520 setSourceDisplay(OUTPUT_MODE_STATE_INIT);
2521 } else if (DISPLAY_TYPE_TV == mDisplayType) {
2522 setSinkDisplay(true);
2523 }
2524#if 0
2525 } else if (DISPLAY_TYPE_TABLET == mDisplayType) {
2526
2527 } else if (DISPLAY_TYPE_REPEATER == mDisplayType) {
2528 setSourceDisplay(OUTPUT_MODE_STATE_INIT);
2529 }
2530#endif
2531
2532 return 0;
2533}
2534
2535void ModePolicy::setSinkDisplay(bool initState) {
2536 char current_mode[MESON_MODE_LEN] = {0};
2537 char outputmode[MESON_MODE_LEN] = {0};
2538
2539 getDisplayMode(current_mode);
2540 getBootEnv(UBOOTENV_OUTPUTMODE, outputmode);
2541 MESON_LOGD("init tv display old outputmode:%s, outputmode:%s\n", current_mode, outputmode);
2542
2543 if (strlen(outputmode) == 0)
2544 strncpy(outputmode, mDefaultUI.c_str(), MESON_MODE_LEN-1);
2545
2546 setSinkOutputMode(outputmode, initState);
2547}
2548
2549void ModePolicy::setSinkOutputMode(const char* outputmode, bool initState) {
2550 [[maybe_unused]] bool sinkInitState = initState;
2551 MESON_LOGI("set sink output mode:%s, init state:%d\n", outputmode, sinkInitState);
2552
2553 //set output mode
2554 char curMode[MESON_MODE_LEN] = {0};
2555 getDisplayMode(curMode);
2556
2557 MESON_LOGI("curMode = %s outputmode = %s", curMode, outputmode);
2558 if (strstr(curMode, outputmode) == NULL) {
2559 setDisplayMode(outputmode);
2560 }
2561
2562 char defVal[PROPERTY_VALUE_MAX] = "0x0";
2563 if (sys_get_bool_prop(PROP_DISPLAY_SIZE_CHECK, true)) {
2564 char resolution[MESON_MODE_LEN] = {0};
2565 char defaultResolution[MESON_MODE_LEN] = {0};
2566 char finalResolution[MESON_MODE_LEN] = {0};
2567 int w = 0, h = 0, w1 =0, h1 = 0;
2568 sysfs_get_string(SYS_DISPLAY_RESOLUTION, resolution, MESON_MODE_LEN);
2569
2570 sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal);
2571 sscanf(resolution, "%dx%d", &w, &h);
2572 sscanf(defaultResolution, "%dx%d", &w1, &h1);
2573 if ((w != w1) || (h != h1)) {
2574 if (strstr(outputmode, "null") && w1 != 0) {
2575 sprintf(finalResolution, "%dx%d", w1, h1);
2576 } else {
2577 sprintf(finalResolution, "%dx%d", w, h);
2578 }
2579 sys_set_prop(PROP_AMDV_PRIORITY, finalResolution);
2580 }
2581 }
2582
2583 char defaultResolution[MESON_MODE_LEN] = {0};
2584 sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal);
2585 MESON_LOGI("set display-size:%s\n", defaultResolution);
2586
2587 //update hwc windows size
2588 int position[4] = { 0, 0, 0, 0 };//x,y,w,h
2589 getPosition(outputmode, position);
2590 setPosition(outputmode, position[0], position[1],position[2], position[3]);
2591
2592 //update hdr policy
2593 if ((isMboxSupportDV() == false)) {
2594 if (sys_get_bool_prop(PROP_AMDV_FEATURE, false)) {
2595 char hdr_policy[MESON_MODE_LEN] = {0};
2596 getHdrStrategy(hdr_policy);
2597 if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) {
2598 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
2599 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) {
2600 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
2601 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE])) {
2602 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]);
2603 }
2604 } else {
2605 initHdrSdrMode();
2606 }
2607 }
2608
2609 if (isMboxSupportDV()) {
2610 if (isTvDVEnable()) {
2611 setTvDVEnable();
2612 } else {
2613 setTvDVDisable();
2614 }
2615 }
2616
2617 //audio
2618 char value[MESON_MAX_STR_LEN] = {0};
2619 memset(value, 0, sizeof(0));
2620 getBootEnv(UBOOTENV_DIGITAUDIO, value);
2621 setDigitalMode(value);
2622
2623 //save output mode
2624 char finalMode[MESON_MODE_LEN] = {0};
2625 getDisplayMode(finalMode);
2626 if (DISPLAY_TYPE_TABLET != mDisplayType) {
2627 setBootEnv(UBOOTENV_OUTPUTMODE, (char *)finalMode);
2628 }
2629 if (strstr(finalMode, "cvbs") != NULL) {
2630 setBootEnv(UBOOTENV_CVBSMODE, (char *)finalMode);
2631 } else if (strstr(finalMode, "hz") != NULL) {
2632 setBootEnv(UBOOTENV_HDMIMODE, (char *)finalMode);
2633 }
2634
2635 MESON_LOGI("set output mode:%s done\n", finalMode);
2636}
2637
2638bool ModePolicy::isHdmiUsed() {
2639 bool ret = true;
2640 char hdmi_state[MESON_MODE_LEN] = {0};
2641
2642 sysfs_get_string(DISPLAY_HDMI_USED, hdmi_state, MESON_MODE_LEN);
2643
2644 if (strstr(hdmi_state, "1") == NULL) {
2645 ret = false;
2646 }
2647
2648 return ret;
2649}
2650
2651bool ModePolicy::isConnected() {
2652 bool ret = ((mConnectorType == CONN_TYPE_HDMI) &&
2653 (mConnector->connection == DRM_MODE_CONNECTED));
2654 return ret;
2655}
2656
2657bool ModePolicy::isVMXCertification() {
2658 return sys_get_bool_prop(PROP_VMX, false);
2659}
2660
2661bool ModePolicy::isHdmiEdidParseOK() {
2662 bool ret = true;
2663
2664 char edidParsing[MESON_MODE_LEN] = {0};
2665 sysfs_get_string(DISPLAY_EDID_STATUS, edidParsing, MESON_MODE_LEN);
2666
2667 if (strcmp(edidParsing, "ok")) {
2668 ret = false;
2669 }
2670
2671 return ret;
2672}
2673
2674bool ModePolicy::isBestPolicy() {
2675 char isBestMode[MESON_MODE_LEN] = {0};
2676 if (DISPLAY_TYPE_TV == mDisplayType) {
2677 return false;
2678 }
2679
2680 return !getBootEnv(UBOOTENV_ISBESTMODE, isBestMode) || strcmp(isBestMode, "true") == 0;
2681}
2682
2683bool ModePolicy::isBestColorSpace() {
2684 bool ret = false;
2685 char user_colorattr[MESON_MODE_LEN] = {0};
2686 if (DISPLAY_TYPE_TV == mDisplayType) {
2687 return false;
2688 }
2689
2690 ret = getBootEnv(UBOOTENV_USER_COLORATTRIBUTE, user_colorattr);
2691
2692 if (!ret) {
2693 return true;
2694 } else if (strstr(user_colorattr, "bit") == NULL) {
2695 return true;
2696 }
2697
2698 return false;
2699}
2700
2701void ModePolicy::setDefaultMode() {
2702 MESON_LOGE("EDID parsing error detected\n");
2703
2704 // check hdmi output mode
2705 char curDisplayMode[MESON_MODE_LEN] = {0};
2706 getDisplayMode(curDisplayMode);
2707
2708 if (!isMatchMode(curDisplayMode, MESON_DEFAULT_HDMI_MODE)) {
2709 //set default color format
2710 setDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, MESON_DEFAULT_COLOR_FORMAT);
2711 //set default resolution
2712 setDisplayMode(MESON_DEFAULT_HDMI_MODE);
2713
2714 //update display position
2715 int position[4] = { 0, 0, 0, 0 };//x,y,w,h
2716 getPosition(MESON_DEFAULT_HDMI_MODE, position);
2717 setPosition(MESON_DEFAULT_HDMI_MODE, position[0], position[1],position[2], position[3]);
2718 } else {
2719 MESON_LOGI("cur mode is default mode\n");
2720 }
2721}
2722
leng.fang3c0ab6d2024-08-01 16:29:00 +08002723void ModePolicy::setDisplay(output_mode_state state)
2724{
2725 if ((state == OUTPUT_MODE_STATE_INIT) ||
2726 (state == OUTPUT_MODE_STATE_POWER)) {
2727 memset(&mConData, 0, sizeof(meson_policy_in));
2728 memset(&mDvInfo, 0, sizeof(hdmi_amdv_info_t));
2729 mState = state;
2730 mConData.state = static_cast<meson_mode_state>(state);
leng.fang91856072024-06-07 14:12:54 +08002731
leng.fang3c0ab6d2024-08-01 16:29:00 +08002732 getConnectorData(&mConData, &mDvInfo);
2733 if (isTvSupportDV() && isMboxSupportDV()) {
2734 strcpy(mDvInfo.amdv_enable, "1");
2735 mConData.hdr_info.is_amdv_enable = isDVEnable();
2736 }
2737
2738 strcpy(mConData.cur_displaymode, mConData.con_info.ubootenv_hdmimode);
2739 }
2740
2741 // TOD sceneProcess
2742 if (isBestPolicy()) {
2743 if (state == OUTPUT_MODE_STATE_INIT || mPolicy == MESON_POLICY_INVALID) {
2744 mPolicy = MESON_POLICY_MIX;
2745 }
2746 } else {
2747 mPolicy = MESON_POLICY_INVALID;
2748 }
2749
2750 meson_mode_set_policy(mModeConType, mPolicy);
2751 meson_mode_set_policy_input(mModeConType, &mConData);
2752 meson_mode_get_policy_output(mModeConType, &mSceneOutInfo);
2753
2754 //5. apply settings to driver
2755 applyDisplaySetting(state == OUTPUT_MODE_STATE_POWER);
2756}
leng.fang91856072024-06-07 14:12:54 +08002757/*
2758 * OUTPUT_MODE_STATE_INIT for boot
2759 * OUTPUT_MODE_STATE_POWER for hdmi plug and suspend/resume
2760 */
2761void ModePolicy::setSourceDisplay(output_mode_state state) {
2762 std::lock_guard<std::mutex> lock(mMutex);
2763
2764 //1. hdmi used and hpd = 0
2765 //set dummy_l mode
2766 if ((isHdmiUsed() == true) && (isConnected() == false)) {
leng.fang3c0ab6d2024-08-01 16:29:00 +08002767 MESON_LOGD("hdmi usd, set cvbs");
2768 setDisplay(state);
leng.fang91856072024-06-07 14:12:54 +08002769 MESON_LOGI("hdmi used but plugout when boot\n");
2770 return;
2771 }
2772
2773 //2. hdmi edid parse error and hpd = 1
2774 //set default reolsution and color format
2775 if ((isHdmiEdidParseOK() == false) &&
2776 (isConnected() == true)) {
2777 setDefaultMode();
2778 return;
2779 }
2780
2781 //3. update hdmi info when boot and hdmi plug/suspend/resume
2782 if ((state == OUTPUT_MODE_STATE_INIT) ||
2783 (state == OUTPUT_MODE_STATE_POWER)) {
2784 memset(&mConData, 0, sizeof(meson_policy_in));
2785 memset(&mDvInfo, 0, sizeof(hdmi_amdv_info_t));
2786 mState = state;
2787 mConData.state = static_cast<meson_mode_state>(state);
2788
2789 getConnectorData(&mConData, &mDvInfo);
2790 if (isTvSupportDV() && isMboxSupportDV()) {
2791 strcpy(mDvInfo.amdv_enable, "1");
2792 mConData.hdr_info.is_amdv_enable = isDVEnable();
2793 }
2794
2795 strcpy(mConData.cur_displaymode, mConData.con_info.ubootenv_hdmimode);
2796 }
2797
2798 // TOD sceneProcess
2799 if (isBestPolicy()) {
2800 if (state == OUTPUT_MODE_STATE_INIT || mPolicy == MESON_POLICY_INVALID) {
2801 mPolicy = MESON_POLICY_MIX;
2802 }
2803 } else {
2804 mPolicy = MESON_POLICY_INVALID;
2805 }
2806
2807 meson_mode_set_policy(mModeConType, mPolicy);
2808 meson_mode_set_policy_input(mModeConType, &mConData);
2809 meson_mode_get_policy_output(mModeConType, &mSceneOutInfo);
2810
2811 //5. apply settings to driver
2812 applyDisplaySetting(state == OUTPUT_MODE_STATE_POWER);
2813}
2814
leng.fang5ec9b6c2024-07-29 14:25:00 +08002815void ModePolicy::setSourceOutputModeNoLock(const char* outputmode, bool force) {
leng.fang91856072024-06-07 14:12:54 +08002816 if (DISPLAY_TYPE_TV == mDisplayType) {
2817 setSinkOutputMode(outputmode, false);
2818 } else {
2819
2820 getConnectorUserData(&mConData, &mDvInfo);
2821
2822 getHdrUserInfo(&mConData.hdr_info);
2823
2824 mState = OUTPUT_MODE_STATE_SWITCH;
2825 mConData.state = static_cast<meson_mode_state>(mState);
2826
2827 strcpy(mConData.cur_displaymode, outputmode);
2828 meson_mode_set_policy_input(mModeConType, &mConData);
2829 meson_mode_get_policy_output(mModeConType, &mSceneOutInfo);
2830
2831 applyDisplaySetting(force);
2832 }
2833}
2834
leng.fang5ec9b6c2024-07-29 14:25:00 +08002835void ModePolicy::setSourceOutputMode(const char* outputmode, bool force) {
2836 std::lock_guard<std::mutex> lock(mMutex);
2837
2838 setSourceOutputModeNoLock(outputmode, force);
2839}
2840
leng.fang91856072024-06-07 14:12:54 +08002841void ModePolicy::getConnectorUserData(struct meson_policy_in* data, hdmi_amdv_info_t *dinfo) {
2842 if (!data || !dinfo) {
2843 MESON_LOGE("%s data is NULL\n", __FUNCTION__);
2844 return;
2845 }
2846
2847 bool ret = false;
2848
2849 //hdmi color space best policy flag
2850 data->con_info.is_bestcolorspace = isBestColorSpace();
2851
2852 MESON_LOGI("isbestColorspace:%d\n",
2853 data->con_info.is_bestcolorspace);
2854
2855 getDisplayMode(mCurrentMode);
2856 ret = getBootEnv(UBOOTENV_HDMIMODE, data->con_info.ubootenv_hdmimode);
2857 if (!ret) {
2858 //if env is null,use none as default value
2859 strcpy(data->con_info.ubootenv_hdmimode, "none");
2860 }
2861 getBootEnv(UBOOTENV_CVBSMODE, data->con_info.ubootenv_cvbsmode);
2862 MESON_LOGI("hdmi_current_mode:%s, ubootenv hdmimode:%s cvbsmode:%s\n",
2863 mCurrentMode,
2864 data->con_info.ubootenv_hdmimode,
2865 data->con_info.ubootenv_cvbsmode);
2866
2867 ret = getBootEnv(UBOOTENV_USER_COLORATTRIBUTE, data->con_info.ubootenv_colorattr);
2868 if (!ret) {
2869 //if env is null,use none as default value
2870 strcpy(data->con_info.ubootenv_colorattr, "none");
2871 }
2872 MESON_LOGI("ubootenv_colorattribute:%s\n",
2873 data->con_info.ubootenv_colorattr);
2874
2875 //if no dolby_status env set to std for enable dv
2876 //if box support dv
2877 char amdv_enable[MESON_MODE_LEN];
2878 ret = getBootEnv(UBOOTENV_DV_ENABLE, amdv_enable);
2879 if (ret) {
2880 strcpy(dinfo->amdv_enable, amdv_enable);
2881 } else if (isMboxSupportDV()) {
2882 strcpy(dinfo->amdv_enable, "1");
2883 } else {
2884 strcpy(dinfo->amdv_enable, "0");
2885 }
2886 MESON_LOGI("dv_enable:%s\n", dinfo->amdv_enable);
2887
2888 char ubootenv_amdv_type[MESON_MODE_LEN];
2889 ret = getBootEnv(UBOOTENV_USER_DV_TYPE, ubootenv_amdv_type);
2890 if (ret) {
2891 strcpy(dinfo->ubootenv_amdv_type, ubootenv_amdv_type);
2892 } else if (isMboxSupportDV()) {
2893 strcpy(dinfo->ubootenv_amdv_type, "1");
2894 } else {
2895 strcpy(dinfo->ubootenv_amdv_type, "0");
2896 }
2897 MESON_LOGI("ubootenv_dv_type:%s\n", dinfo->ubootenv_amdv_type);
2898}
2899
2900void ModePolicy::drmMode2MesonMode(meson_mode_info_t &mesonMode, drm_mode_info_t &drmMode) {
2901 strncpy(mesonMode.name, drmMode.name, MESON_MODE_LEN);
2902 mesonMode.dpi_x = drmMode.dpiX;
2903 mesonMode.dpi_y = drmMode.dpiY;
2904 mesonMode.pixel_w = drmMode.pixelW;
2905 mesonMode.pixel_h = drmMode.pixelH;
2906 mesonMode.refresh_rate = drmMode.refreshRate;
2907 mesonMode.group_id = drmMode.groupId;
2908}
2909
2910void ModePolicy::getSupportedModes() {
2911 //pthread_mutex_lock(&mEnvLock);
2912 std::map<uint32_t, drm_mode_info_t> connecterModeList;
2913
2914 /* reset ModeList */
2915 mModes.clear();
2916 if (mConnector->connection == DRM_MODE_CONNECTED) {
2917 getModes(mConnector, connecterModeList);
2918
2919 for (auto it = connecterModeList.begin(); it != connecterModeList.end(); it++) {
2920 // All modes are supported
2921 if (isModeSupported(it->second)) {
2922 mModes.emplace(mModes.size(), it->second);
2923 }
2924 }
2925 }
2926
2927 /* transfer to meson_mode_info_t */
2928 auto conPtr = &mConData.con_info;
2929 conPtr->modes_size = mModes.size();
2930 if (conPtr->modes_size > conPtr->modes_capacity) {
2931 // realloc memory
2932 void * buff = realloc(conPtr->modes, conPtr->modes_size * sizeof(meson_mode_info_t));
2933 MESON_ASSERT(buff, "modePolicy realloc but has no memory");
2934 conPtr->modes = (meson_mode_info_t *) buff;
2935 conPtr->modes_capacity = conPtr->modes_size;
2936 }
2937
2938 int i = 0;
2939 for (auto it = mModes.begin(); it != mModes.end(); it++) {
2940 drmMode2MesonMode(conPtr->modes[i], it->second);
2941 i++;
2942 }
2943}
2944
2945bool ModePolicy::getModeNameForPix(char *name,
2946 int32_t width, int32_t height, uint32_t refresh, uint32_t flags)
2947{
2948 std::map<uint32_t, drm_mode_info_t> connecterModeList;
2949 drm_mode_info_t mode;
2950 int current_interlaced;
2951 bool ret = false;
2952
2953 if (!mConnector || mConnector->connection != DRM_MODE_CONNECTED)
2954 return false;
2955
2956 drmModeModeInfoPtr drmModes = mConnector->modes;
2957
2958 for (int i = 0;i < mConnector->count_modes; i++) {
2959 current_interlaced = (drmModes[i].flags & DRM_MODE_FLAG_INTERLACE);
2960 if (drmModes[i].hdisplay == width && drmModes[i].vdisplay == height &&
2961 drmModes[i].vrefresh == refresh &&
2962 current_interlaced == (flags & DRM_MODE_FLAG_INTERLACE)) {
2963 strcpy(name, drmModes[i].name);
2964 ret = true;
2965 break;
2966 }
2967 }
2968 return ret;
2969}
2970
2971bool ModePolicy::isModeSupported(drm_mode_info_t mode) {
2972 bool ret = false;
2973 uint32_t i;
2974
2975 for (i = 0; i < ARRAY_SIZE(DISPLAY_MODE_LIST); i++) {
2976 if (!strcmp(DISPLAY_MODE_LIST[i], mode.name)) {
2977 ret = true;
2978 break;
2979 }
2980 }
2981
2982 return ret;
2983}
2984
2985int32_t bindCrtcAndConnector(drmModeCrtc *crtc, drmModeConnector *conn)
2986{
2987 int ret = -1;
2988 MESON_LOGI("bindCrtcAndConnector:%p, %p\n", crtc, conn);
2989 if (g_Policy.get()) {
2990 ret = g_Policy->bindConnector(conn);
2991 ret |= g_Policy->bindCrtc(crtc);
2992 }
2993 return ret;
2994}
2995
2996void initModePolicyFun(drmModeCrtc *crtc, drmModeConnector *conn, CompositorFunctionCallBack callback)
2997{
2998 if (!g_Adapter.get())
2999 g_Adapter = std::make_shared<DisplayAdapter>(crtc, conn);
3000
3001 if (!g_Policy.get())
3002 g_Policy = std::make_shared<ModePolicy>(g_Adapter, 0);
3003
3004 if (g_Policy.get() && g_Adapter.get()) {
3005 g_Adapter->registerCallBack(callback);
3006 bindCrtcAndConnector(crtc, conn);
3007 }
3008}
3009
3010void initModePolicy(drmModeCrtc *crtc, drmModeConnector *conn, CompositorFunctionCallBack callback)
3011{
3012 //initModePolicyFun(crtc, conn,callback);
3013 if (g_Policy.get()) {
3014 g_Policy->initialize();
3015 }
3016}
3017
3018void onHotplug(bool connected)
3019{
3020 if (g_Policy.get())
3021 g_Policy->onHotplug(connected);
3022}
3023
3024void getPreferredBootConfig(char *name)
3025{
3026 std::string mode;
3027 if (g_Policy.get()) {
3028 if (g_Policy->getPreferredBootConfig(mode) == 0)
3029 strcpy(name, mode.c_str());
3030 }
3031}
3032
3033void setHdrConversionPolicy(bool passthrough, int32_t forceType)
3034{
3035 if (g_Policy.get())
3036 g_Policy->setHdrConversionPolicy(passthrough, forceType);
3037}
3038
3039void setDvMode(int amdv_mode)
3040{
3041 std::string mode = to_string(amdv_mode);
3042 if (g_Policy.get())
3043 g_Policy->setDvMode(mode);
3044}
3045
3046void setColorSpace(char *colorspace)
3047{
3048 std::string color = colorspace;
3049 if (g_Policy.get())
3050 g_Policy->setColorSpace(color);
3051}
3052
3053void setBootConfig(char *mode, bool auto_mode)
3054{
3055 std::string config = mode;
3056 if (g_Policy.get()) {
3057 if (auto_mode)
3058 g_Policy->clearBootConfig();
3059 else
3060 g_Policy->setBootConfig(config);
3061 }
3062}
3063
3064bool setActiveConfig(char *mode)
3065{
3066 std::string config = mode;
3067 if (g_Policy.get()) {
3068 g_Policy->setActiveConfig(config);
3069 return true;
3070 }
3071 return false;
3072}
3073
3074bool setPolicyByAppName(const char *name, int state)
3075{
3076 if (g_Policy.get()) {
3077 if (state == 1 && !strcmp(name, "netflix")) {
3078 g_Policy->setPolicy(MESON_POLICY_BEST);
3079 } else {
3080 g_Policy->setPolicy(MESON_POLICY_MIX);
3081 }
3082 return true;
3083 }
3084 return false;
3085}
3086
3087bool updateEnv()
3088{
3089 if (g_Policy.get())
3090 return g_Policy->updateEnv();
3091 return false;
3092}
3093
3094bool getModeNameForPix(char *name,
3095 int32_t width, int32_t height, uint32_t refresh, uint32_t flags)
3096{
3097 if (g_Policy.get())
3098 return g_Policy->getModeNameForPix(name, width, height, refresh / 1000, flags);
3099 return false;
3100}