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