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