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