blob: 88956d1df8f60baead696d4ac10b1fe55ae8a802 [file] [log] [blame]
leng.fang91856072024-06-07 14:12:54 +08001/*
2 * Copyright (c) 2022 Amlogic, Inc. All rights reserved.
3 *
4 * This source code is subject to the terms and conditions defined in the
5 * file 'LICENSE' which is part of this source code package.
6 *
7 * Description:
8 */
9
10#include "ModePolicy.h"
11#include "mode_ubootenv.h"
12#include <inttypes.h>
13#include <sys/utsname.h>
14#include <memory>
limin.tiana9a091a2024-09-23 07:54:32 +000015#include <sys/ioctl.h>
16
leng.fang91856072024-06-07 14:12:54 +080017//#include <systemcontrol.h>
18static int g_activeLevel= 3;
19
20/* testing if tv support this displaymode and deepcolor combination, then if cat result is 1: support, 0: not */
21#define DISPLAY_HDMI_VALID_MODE "/sys/class/amhdmitx/amhdmitx0/valid_mode"
22
23#define PROP_DEFAULT_COLOR "ro_vendor_platform_default_color"
24#define LOW_POWER_DEFAULT_COLOR "ro_vendor_low_power_default_color" /* Set default deep color is 8bit for Low Power Mode */
25#define UBOOTENV_COLORATTRIBUTE "ubootenv.var.colorattribute"
26
27#define EDID_MAX_SIZE 2049
28#define MODE_8K4K_PREFIX "4320p"
29#define PROP_VALUE_MAX 92
30
chen.wang10698b432024-11-12 13:08:14 +000031#define HDMI_HDR_STATUS_HDR10PLUS 0
32#define HDMI_HDR_STATUS_DolbyVision_STD 1
33#define HDMI_HDR_STATUS_DolbyVision_Lowlatency 2
34#define HDMI_HDR_STATUS_HDR10_ST2084 3
35#define HDMI_HDR_STATUS_HDR10_TRADITIONAL 4
36#define HDMI_HDR_STATUS_HDR_HLG 5
37#define HDMI_HDR_STATUS_SDR 6
38
leng.fang91856072024-06-07 14:12:54 +080039enum {
40 DISPLAY_TYPE_NONE = 0,
41 DISPLAY_TYPE_TABLET = 1,
42 DISPLAY_TYPE_MBOX = 2,
43 DISPLAY_TYPE_TV = 3,
44 DISPLAY_TYPE_REPEATER = 4
45};
46
leng.fang91856072024-06-07 14:12:54 +080047static const char* AMDV_MODE_TYPE[] = {
48 "DV_RGB_444_8BIT",
49 "DV_YCbCr_422_12BIT",
50 "LL_YCbCr_422_12BIT",
51 "LL_RGB_444_10BIT",
52 "LL_RGB_444_12BIT"
53};
54
55static const char* ALLM_MODE_CAP[] = {
56 "0",
57 "1",
58};
59
60static const char* ALLM_MODE[] = {
61 "-1",
62 "0",
63 "1",
64};
65
66static const char* CONTENT_TYPE_CAP[] = {
67 "graphics",
68 "photo",
69 "cinema",
70 "game",
71};
72
73/*****************************************/
74/* deepcolor */
75
76//this is check hdmi mode(4K60/4k50) list
77static const char* COLOR_ATTRIBUTE_LIST[] = {
78 COLOR_RGB_8BIT,
79 COLOR_YCBCR444_8BIT,
80 COLOR_YCBCR420_8BIT,
81 COLOR_YCBCR422_8BIT,
82};
83
84//this is check hdmi mode list
85static const char* COLOR_ATTRIBUTE_LIST_8BIT[] = {
86 COLOR_RGB_8BIT,
87 COLOR_YCBCR444_8BIT,
88 COLOR_YCBCR422_8BIT,
89};
90
91std::shared_ptr<ModePolicy> g_Policy;
92std::shared_ptr<DisplayAdapter> g_Adapter;
93
94ModePolicy::ModePolicy() {
95 mDisplayType = DISPLAY_TYPE_MBOX;
96 mPolicy = MESON_POLICY_MIX;
97 mReason = OUTPUT_CHANGE_BY_INIT;
98 mDisplayId = 0;
99 memset(&mConnectorType, 0, sizeof(mConnectorType));
100 memset(&mModeConType, 0, sizeof(mModeConType));
101 memset(&mConData, 0, sizeof(mConData));
102 memset(&mSceneOutInfo, 0, sizeof(mSceneOutInfo));
103 memset(&mState, 0, sizeof(mState));
104 memset(&mDvInfo, 0, sizeof(mDvInfo));
105 mDisplayWidth = 0;
106 mDisplayHeight = 0;
107 mFracMode = MODE_FRACTION;
leng.fangc81d8672024-07-11 10:14:46 +0800108 mEnvLock = PTHREAD_MUTEX_INITIALIZER;
limin.tiana9a091a2024-09-23 07:54:32 +0000109 mSeamlessSwitchEnabled = true;
leng.fang91856072024-06-07 14:12:54 +0800110}
111
112ModePolicy::ModePolicy(std::shared_ptr<DisplayAdapter> adapter, const uint32_t displayId) {
113 mAdapter = adapter;
114 mDisplayType = DISPLAY_TYPE_MBOX;
115 mPolicy = MESON_POLICY_MIX;
116 mReason = OUTPUT_CHANGE_BY_INIT;
117 mDisplayId = displayId;
118 memset(&mConnectorType, 0, sizeof(mConnectorType));
119 memset(&mModeConType, 0, sizeof(mModeConType));
120 memset(&mConData, 0, sizeof(mConData));
121 memset(&mSceneOutInfo, 0, sizeof(mSceneOutInfo));
122 memset(&mState, 0, sizeof(mState));
123 memset(&mDvInfo, 0, sizeof(mDvInfo));
124 mDisplayWidth = 0;
125 mDisplayHeight = 0;
126 mFracMode = MODE_FRACTION;
leng.fangc81d8672024-07-11 10:14:46 +0800127 mEnvLock = PTHREAD_MUTEX_INITIALIZER;
limin.tiana9a091a2024-09-23 07:54:32 +0000128 mSeamlessSwitchEnabled = true;
leng.fang91856072024-06-07 14:12:54 +0800129}
130
131ModePolicy::~ModePolicy() {
132
133}
134
135bool ModePolicy::getBootEnv(const char *key, char *value) {
136 const char* p_value;
137 const char* envName = key;
138 if (strstr(key, PROFIX_UBOOTENV_VAR) != NULL)
139 envName = key + strlen(PROFIX_UBOOTENV_VAR);
140 p_value = bootenv_get(envName);
141 MESON_LOGD("get key:%s value:%s", key, p_value ? p_value : "novalue");
142
143 if (p_value) {
144 strcpy(value, p_value);
145 return true;
146 }
147
148 return false;
149}
150
151int ModePolicy::getBootenvInt(const char* key, int defaultVal) {
152 int value = defaultVal;
153 const char* p_value;
154 const char* envName = key;
155 if (strstr(key, PROFIX_UBOOTENV_VAR) != NULL)
156 envName = key + strlen(PROFIX_UBOOTENV_VAR);
157 p_value = bootenv_get(envName);
158 if (p_value) {
159 value = atoi(p_value);
160 }
161 return value;
162}
163
164void ModePolicy::setBootEnv(const char* key, const char* value) {
leng.fang13fd3982024-07-03 19:09:58 +0800165 const char* p_value;
leng.fang91856072024-06-07 14:12:54 +0800166 const char* envName = key;
167 if (strstr(key, PROFIX_UBOOTENV_VAR) != NULL)
168 envName = key + strlen(PROFIX_UBOOTENV_VAR);
leng.fang13fd3982024-07-03 19:09:58 +0800169 p_value = bootenv_get(envName);
170
171 if (p_value && !strcmp(p_value, value)) {
172 MESON_LOGV("value is equal, do not set");
173 return;
174 }
175
176 MESON_LOGD("set key:%s value:%s", key, value);
leng.fang91856072024-06-07 14:12:54 +0800177 bootenv_update(envName, value);
178}
179
180
181// TODO: need refactor
182#ifdef HDR_AMDV_PROPERTY
183void ModePolicy::getDvCap(struct meson_hdr_info *data) {
184 if (!data) {
185 MESON_LOGE("%s data is NULL\n", __FUNCTION__);
186 return;
187 }
188
189 std::string amdv_cap;
190 int cap = 0;
191 getDisplayAttribute(DISPLAY_AMDV_CAP, amdv_cap);
192 strcpy(data->dv_cap, amdv_cap.c_str());
193 cap = atoi(data->dv_cap);
194
195 if (cap != 0) {
196 uint32_t index = (cap & (1 << 2)) ? 19 : 17;
197 if ((strlen(data->dv_max_mode) + strlen(DISPLAY_MODE_LIST[index]) + 1) < sizeof(data->dv_max_mode)) {
198 strcat(data->dv_max_mode, DISPLAY_MODE_LIST[index]);
199 strcat(data->dv_max_mode, ",");
200 } else {
201 MESON_LOGE("DisplayMode strcat overflow: src=%s, dst=%s\n", DISPLAY_MODE_LIST[index], data->dv_max_mode);
202 }
203
204 index = ((cap & 0xf8) >> 3);
205 for (int i = 0; i < ARRAY_SIZE(AMDV_MODE_TYPE); i++) {
206 if (index & (1 << i)) {
207 strcat(data->dv_deepcolor, AMDV_MODE_TYPE[i]);
208 strcat(data->dv_deepcolor, ",");
209 }
210 }
211 }
212}
213#else
214void ModePolicy::getDvCap(struct meson_hdr_info *data) {
215 if (!data) {
216 MESON_LOGE("%s data is NULL\n", __FUNCTION__);
217 return;
218 }
219
220 std::string amdv_cap;
221 getDisplayAttribute(DISPLAY_AMDV_CAP2, amdv_cap);
222 strcpy(data->dv_cap, amdv_cap.c_str());
223
224 if (strstr(data->dv_cap, "DolbyVision RX support list") != NULL) {
225 memset(data->dv_max_mode, 0, sizeof(data->dv_max_mode));
226 memset(data->dv_deepcolor, 0, sizeof(data->dv_deepcolor));
227 for (int i = ARRAY_SIZE(DISPLAY_MODE_LIST) - 1; i >= 0; i--) {
228 if (strstr(data->dv_cap, DISPLAY_MODE_LIST[i]) != NULL) {
229 if ((strlen(data->dv_max_mode) + strlen(DISPLAY_MODE_LIST[i]) + 1) < sizeof(data->dv_max_mode)) {
230 strcpy(data->dv_max_mode, DISPLAY_MODE_LIST[i]);
231 } else {
232 MESON_LOGE("DisplayMode strcat overflow: src=%s, dst=%s\n", DISPLAY_MODE_LIST[i], data->dv_max_mode);
233 }
234 break;
235 }
236 }
237
238 for (int i = 0; i < sizeof(AMDV_MODE_TYPE)/sizeof(AMDV_MODE_TYPE[0]); i++) {
239 if (strstr(data->dv_cap, AMDV_MODE_TYPE[i])) {
240 if ((strlen(data->dv_deepcolor) + strlen(AMDV_MODE_TYPE[i]) + 2) < sizeof(data->dv_deepcolor)) {
241 strcat(data->dv_deepcolor, AMDV_MODE_TYPE[i]);
242 strcat(data->dv_deepcolor, ",");
243 } else {
244 MESON_LOGE("DisplayMode strcat overflow: src=%s, dst=%s\n", AMDV_MODE_TYPE[i], data->dv_deepcolor);
245 break;
246 }
247 }
248 }
249 MESON_LOGI("TV dv info: mode:%s deepcolor: %s\n", data->dv_max_mode, data->dv_deepcolor);
250 } else {
251 MESON_LOGE("TV isn't support dv: %s\n", data->dv_cap);
252 }
253}
254#endif
255
256void ModePolicy::getHdmiDcCap(char* dc_cap, int32_t len) {
257 if (!dc_cap) {
258 MESON_LOGE("%s dc_cap is NULL\n", __FUNCTION__);
259 return;
260 }
261
262 int count = 0;
263 while (true) {
264 sysfs_get_string_original(DISPLAY_HDMI_DEEP_COLOR, dc_cap, len);
265 if (strlen(dc_cap) > 0)
266 break;
267
268 if (count >= 5) {
269 MESON_LOGE("read dc_cap fail\n");
270 break;
271 }
272 count++;
273 usleep(500000);
274 }
275}
276
277int ModePolicy::getHdmiSinkType() {
278 char sinkType[MESON_MODE_LEN] = {0};
279 if (sysfs_get_string(DISPLAY_HDMI_SINK_TYPE, sinkType, MESON_MODE_LEN) != 0)
280 return HDMI_SINK_TYPE_NONE;
281
282 if (NULL != strstr(sinkType, "sink")) {
283 return HDMI_SINK_TYPE_SINK;
284 } else if (NULL != strstr(sinkType, "repeater")) {
285 return HDMI_SINK_TYPE_REPEATER;
286 } else {
287 return HDMI_SINK_TYPE_NONE;
288 }
289}
290
291void ModePolicy::getHdmiEdidStatus(char* edidstatus, int32_t len) {
292 if (!edidstatus) {
293 MESON_LOGE("%s edidstatus is NULL\n", __FUNCTION__);
294 return;
295 }
296
297 sysfs_get_string(DISPLAY_EDID_STATUS, edidstatus, len);
298}
299
300int32_t ModePolicy::setHdrStrategy(int32_t policy, const char *type) {
301 SYS_LOGI("%s type:%s policy:%s", __func__,
302 meson_hdrPolicyToString(policy), type);
303
304 //1. update env policy
305 std::string value = std::to_string(policy);
306 setBootEnv(UBOOTENV_HDR_POLICY, value.c_str());
307
308 if (policy == MESON_HDR_POLICY_SOURCE) {
309 if (isDVEnable()) {
310 setBootEnv(UBOOTENV_DOLBYSTATUS, "0");
311 }
312 } else {
313 char dvstatus[MESON_MODE_LEN] = {0};
314 if (isDVEnable()) {
leng.fangd8ab2872024-06-28 16:23:43 +0800315 sprintf(dvstatus, "%d", mSceneOutInfo.amdv_type);
leng.fang91856072024-06-07 14:12:54 +0800316 setBootEnv(UBOOTENV_DOLBYSTATUS, dvstatus);
317 }
318 }
319
320 int32_t priority = MESON_HDR10_PRIORITY;
321 value = std::to_string(MESON_HDR10_PRIORITY);
322 if (strstr(type, AMDV_DISABLE_FORCE_SDR)) {
323 priority = MESON_SDR_PRIORITY;
324 value = std::to_string(MESON_SDR_PRIORITY);
325 }
326
327 //2. set current hdmi mode
328 meson_mode_set_policy_input(mModeConType, &mConData);
329 getDisplayMode(mCurrentMode);
330
331 if (!meson_mode_support_mode(mModeConType, priority, mCurrentMode)) {
332 setBootEnv(UBOOTENV_HDR_FORCE_MODE, type);
333 setSourceOutputMode(mCurrentMode);
334 } else {
335 MESON_LOGD("%s mode check failed", __func__);
336 return -EINVAL;
337 }
338
339 return 0;
340}
341
342void ModePolicy::getHdrStrategy(char* value) {
343 char hdr_policy[MESON_MODE_LEN] = {0};
344
345 memset(hdr_policy, 0, MESON_MODE_LEN);
346 getBootEnv(UBOOTENV_HDR_POLICY, hdr_policy);
347
348 if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) {
349 strcpy(value, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
350 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) {
351 strcpy(value, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
352 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE])) {
353 strcpy(value, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]);
354 } else if (strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) {
355 strcpy(value, AMDV_POLICY_FORCE_MODE);
356 }
357 MESON_LOGI("get uboot HdrStrategy is [%s]", value);
358}
359
360int32_t ModePolicy::setHdrPriority(int32_t type) {
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
1105 mConnecterModes.clear();
1106 /*add new display mode list.*/
1107 drmModeModeInfoPtr drmModes = connector->modes;
1108 drm_mode_info_t modeInfo;
1109 memset(&modeInfo, 0, sizeof(modeInfo));
1110 for (int i = 0;i < connector->count_modes; i++) {
1111 strncpy(modeInfo.name, drmModes[i].name, DRM_DISPLAY_MODE_LEN - 1);
1112 modeInfo.pixelW = drmModes[i].hdisplay;
1113 modeInfo.pixelH = drmModes[i].vdisplay;
1114 if (connector->mmWidth != 0 && connector->mmHeight != 0) {
1115 modeInfo.dpiX = (modeInfo.pixelW * 25.4f) / connector->mmWidth * 1000;
1116 modeInfo.dpiY = (modeInfo.pixelH * 25.4f) / connector->mmHeight * 1000;
1117 }
1118 modeInfo.refreshRate = drmModes[i].vrefresh;
1119 modeInfo.flags = drmModes[i].flags;
1120
1121 bool bNonFractionMode = false;
1122 if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) {
1123 // default add frac refresh rate config, like 23.976hz, 29.97hz...
1124 if (modeInfo.refreshRate == REFRESH_24kHZ
1125 || modeInfo.refreshRate == REFRESH_30kHZ
1126 || modeInfo.refreshRate == REFRESH_60kHZ
1127 || modeInfo.refreshRate == REFRESH_120kHZ
1128 || modeInfo.refreshRate == REFRESH_240kHZ) {
1129 if (mFracMode == MODE_ALL || mFracMode == MODE_FRACTION) {
1130 drm_mode_info_t fracMode = modeInfo;
1131 fracMode.refreshRate = (modeInfo.refreshRate * 1000) / (float)1001;
1132 fracMode.groupId = mConnecterModes.size();
1133 mConnecterModes.emplace(mConnecterModes.size(), fracMode);
1134 MESON_LOGD("add fraction display mode (%s)", fracMode.name);
1135 }
1136 } else {
1137 bNonFractionMode = true;
1138 }
1139 }
1140
1141 if (connector->connector_type != DRM_MODE_CONNECTOR_HDMIA ||
1142 mFracMode == MODE_ALL || mFracMode == MODE_NON_FRACTION) {
1143 bNonFractionMode = true;
1144 }
1145 // drm only send frame rate (int)59hz, its real frac refresh rate is 59.94hz
1146 if (modeInfo.refreshRate == 59.00) {
1147 modeInfo.refreshRate = (60 * 1000) / (float)1001;
1148 }
1149
1150 if (bNonFractionMode) {
1151 // add normal refresh rate config, like 24hz, 30hz...
1152 modeInfo.groupId = mConnecterModes.size();
1153 mConnecterModes.emplace(mConnecterModes.size(), modeInfo);
1154 }
1155 MESON_LOGD("add display mode (%s-%s, %dx%d, %f)",
1156 drmModes[i].name, modeInfo.name,
1157 modeInfo.pixelW, modeInfo.pixelH, modeInfo.refreshRate);
1158 }
1159 modes = mConnecterModes;
1160}
1161
1162int32_t ModePolicy::bindConnector(drmModeConnector *connector) {
1163 MESON_ASSERT(connector, "ModePolicy bindConnector get null connector!!");
1164
1165 MESON_LOGI("bindConnector: mConnector: %p\n", mConnector);
1166 std::map<uint32_t, drm_mode_info_t> modes;
1167 getModes(connector, modes);
1168
1169 mConnector = connector;
1170 switch (mConnector->connector_type) {
1171 case DRM_MODE_CONNECTOR_HDMIA:
1172 mDisplayType = DISPLAY_TYPE_MBOX;
1173 mConnectorType = CONN_TYPE_HDMI;
1174 mModeConType = MESON_MODE_HDMI;
1175 break;
1176 case LEGACY_NON_DRM_CONNECTOR_PANEL:
1177 case DRM_MODE_CONNECTOR_LVDS:
1178 case DRM_MODE_CONNECTOR_MESON_LVDS_A:
1179 case DRM_MODE_CONNECTOR_MESON_LVDS_B:
1180 case DRM_MODE_CONNECTOR_MESON_LVDS_C:
1181 case DRM_MODE_CONNECTOR_MESON_VBYONE_A:
1182 case DRM_MODE_CONNECTOR_MESON_VBYONE_B:
1183 case DRM_MODE_CONNECTOR_MESON_MIPI_A:
1184 case DRM_MODE_CONNECTOR_MESON_MIPI_B:
1185 case DRM_MODE_CONNECTOR_MESON_EDP_A:
1186 case DRM_MODE_CONNECTOR_MESON_EDP_B:
1187 mDisplayType = DISPLAY_TYPE_TV;
1188 mConnectorType = CONN_TYPE_PANEL;
1189 mModeConType = MESON_MODE_PANEL;
1190 break;
1191 case DRM_MODE_CONNECTOR_TV:
1192 mDisplayType = DISPLAY_TYPE_MBOX;
1193 mConnectorType = CONN_TYPE_CVBS;
1194 mModeConType = MESON_MODE_HDMI;
1195 break;
1196 default:
1197 MESON_LOGE("bindConnector unknown connector type:%d", mConnector->connector_type);
1198 mDisplayType = DISPLAY_TYPE_MBOX;
1199 mConnectorType = CONN_TYPE_HDMI;
1200 mModeConType = MESON_MODE_HDMI;
1201 break;
1202 }
limin.tiana9a091a2024-09-23 07:54:32 +00001203
leng.fang91856072024-06-07 14:12:54 +08001204 return 0;
1205}
1206
1207int32_t ModePolicy::bindCrtc(drmModeCrtcPtr crtc) {
1208 mCrtc = crtc;
1209 mAdapter->initDisplayAttributeInfo(mCrtc, mConnector);
1210 updateHdrCaps();
1211 return 0;
1212}
1213
1214/* *
1215 * @Description: init dv graphics priority when bootup.
1216 * */
1217void ModePolicy::initGraphicsPriority() {
1218 char mode[MESON_MODE_LEN] = {0};
1219 char defVal[MESON_MODE_LEN] = {"1"};
1220
1221 sys_get_string_prop_default(PROP_AMDV_PRIORITY, mode, defVal);
1222 setDisplayAttribute(DISPLAY_AMDV_GRAPHICS_PRIORITY, mode);
1223 sys_set_prop(PROP_AMDV_PRIORITY, mode);
1224}
1225
1226
1227/* *
1228 * @Description: set hdr mode
1229 * @params: mode "0":off "1":on "2":auto
1230 * */
1231void ModePolicy::setHdrMode(const char* mode) {
1232 if ((atoi(mode) >= 0) && (atoi(mode) <= 2)) {
1233 MESON_LOGI("setHdrMode state: %s\n", mode);
1234 setDisplayAttribute(DISPLAY_HDR_MODE, mode);
1235 sys_set_prop(PROP_HDR_MODE_STATE, mode);
1236 }
1237}
1238
1239/* *
1240 * @Description: set sdr mode
1241 * @params: mode "0":off "2":auto
1242 * */
1243void ModePolicy::setSdrMode(const char* mode) {
1244 if ((atoi(mode) == 0) || atoi(mode) == 2) {
1245 MESON_LOGI("setSdrMode state: %s\n", mode);
1246 setDisplayAttribute(DISPLAY_SDR_MODE, mode);
1247 sys_set_prop(PROP_SDR_MODE_STATE, mode);
1248 setBootEnv(UBOOTENV_SDR2HDR, (char *)mode);
1249 }
1250}
1251
1252
1253void ModePolicy::initHdrSdrMode() {
1254 char mode[MESON_MODE_LEN] = {0};
1255 char defVal[MESON_MODE_LEN] = {HDR_MODE_AUTO};
1256 sys_get_string_prop_default(PROP_HDR_MODE_STATE, mode, defVal);
1257 setHdrMode(mode);
1258 memset(mode, 0, sizeof(mode));
1259 bool flag = sys_get_bool_prop(PROP_ENABLE_SDR2HDR, false);
1260 if (flag & isDVEnable()) {
1261 strcpy(mode, SDR_MODE_OFF);
1262 } else {
1263 strcpy(defVal, flag ? SDR_MODE_AUTO : SDR_MODE_OFF);
1264 sys_get_string_prop_default(PROP_SDR_MODE_STATE, mode, defVal);
1265 }
1266 setSdrMode(mode);
1267}
1268
1269bool ModePolicy::checkDVStatusChanged(int state) {
1270 std::string curDvEnable = "";
1271 std::string curDvLLPolicy = "";
1272 int curDvMode = -1;
1273
1274 getDisplayAttribute(DISPLAY_AMDV_ENABLE, curDvEnable);
1275 getDisplayAttribute(DISPLAY_AMDV_LL_POLICY, curDvLLPolicy);
1276 MESON_LOGI("curDvEnable %s, curDvLLPolicy %s!!\n", curDvEnable.c_str(), curDvLLPolicy.c_str());
1277
1278 if (!strcmp(curDvEnable.c_str(), AMDV_DISABLE) ||
1279 !strcmp(curDvEnable.c_str(), "0"))
1280 curDvMode = AMDV_SET_DISABLE;
1281 else if (!strcmp(curDvLLPolicy.c_str(), "0"))
1282 curDvMode = AMDV_SET_ENABLE;
1283 else if (!strcmp(curDvLLPolicy.c_str(), "1"))
1284 curDvMode = AMDV_SET_ENABLE_LL_YUV;
1285 else if (!strcmp(curDvLLPolicy.c_str(), "2"))
1286 curDvMode = AMDV_SET_ENABLE_LL_RGB;
1287
1288 MESON_LOGI("curDvMode %d, want DvMode %d\n", curDvMode, state);
1289
1290 if (curDvMode != state) {
1291 return true;
1292 } else {
1293 return false;
1294 }
1295}
1296
1297//get edid crc value to check edid change
1298bool ModePolicy::isEdidChange() {
1299 char edid[MESON_MAX_STR_LEN] = {0};
1300 char crcvalue[MESON_MAX_STR_LEN] = {0};
1301 unsigned int crcheadlength = strlen(DEFAULT_EDID_CRCHEAD);
1302 sysfs_get_string(DISPLAY_EDID_VALUE, edid, MESON_MAX_STR_LEN);
1303 char *p = strstr(edid, DEFAULT_EDID_CRCHEAD);
1304 if (p != NULL && strlen(p) > crcheadlength) {
1305 p += crcheadlength;
1306 if (!getBootEnv(UBOOTENV_EDIDCRCVALUE, crcvalue) || strncmp(p, crcvalue, strlen(p))) {
1307 MESON_LOGI("update edidcrc: %s->%s\n", crcvalue, p);
1308 setBootEnv(UBOOTENV_EDIDCRCVALUE, p);
1309 return true;
1310 }
1311 }
1312 return false;
1313}
1314
1315void ModePolicy::saveDeepColorAttr(const char* mode, const char* dcValue) {
1316 char ubootvar[100] = {0};
1317 sprintf(ubootvar, "ubootenv.var.%s_deepcolor", mode);
1318 setBootEnv(ubootvar, (char *)dcValue);
1319}
1320
1321void ModePolicy::saveHdmiParamToEnv() {
1322 char outputMode[MESON_MODE_LEN] = {0};
1323 char dvenable[MESON_MODE_LEN] = {0};
1324
1325 getDisplayMode(outputMode);
1326 if (strlen(mDvInfo.amdv_enable) > 0)
1327 strcpy(dvenable, mDvInfo.amdv_enable);
1328
1329 // 1. check whether the TV changed or not, if changed save crc
1330 if (isEdidChange()) {
1331 MESON_LOGD("tv sink changed\n");
1332 }
1333
1334 // 2. save coloattr/hdmimode to bootenv if mode is not null or dummy_l
1335 if (strstr(outputMode, "cvbs") != NULL) {
1336 setBootEnv(UBOOTENV_CVBSMODE, (char *)outputMode);
1337 } else if (strcmp(outputMode, "null") && strcmp(outputMode, "dummy_l")) {
1338 std::string colorAttr;
1339 char colorDepth[MESON_MODE_LEN] = {0};
1340 char colorSpace[MESON_MODE_LEN] = {0};
1341 char dvstatus[MESON_MODE_LEN] = {0};
1342 char hdr_policy[MESON_MODE_LEN] = {0};
1343 // 2.1 save color attr
1344 getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, colorAttr);
1345 saveDeepColorAttr(outputMode, colorAttr.c_str());
1346 setBootEnv(UBOOTENV_COLORATTRIBUTE, colorAttr.c_str());
1347 //colorDepth&&colorSpace is used for uboot hdmi to find
1348 //best color attributes for the selected hdmi mode when TV changed
1349 char defVal[MESON_MODE_LEN] = {"8"};
1350 sys_get_string_prop_default(PROP_DEEPCOLOR_CTL, colorDepth, defVal);
1351 strcpy(defVal, "auto");
1352 sys_get_string_prop_default(PROP_PIXFMT, colorSpace, defVal);
1353 setBootEnv(UBOOTENV_HDMICOLORDEPTH, colorDepth);
1354 setBootEnv(UBOOTENV_HDMICOLORSPACE, colorSpace);
1355
limin.tian71ee0c22024-08-29 03:36:32 +00001356 // 2.2 save output mode,removed, we use hdmimode for hdmi.
leng.fang91856072024-06-07 14:12:54 +08001357 // 2.3 save dv status/dv_type
1358 // In follow sink mode: 0:disable 1:STD(or enable dv) 2:LL YUV 3: LL RGB
1359 // In follow source mode: dv is disable in uboot.
1360 if (isMboxSupportDV()) {
1361 char hdr_force_mode[MESON_MODE_LEN] = {0};
1362 memset(hdr_force_mode, 0, MESON_MODE_LEN);
1363 getBootEnv(UBOOTENV_HDR_FORCE_MODE, hdr_force_mode);
1364 getHdrStrategy(hdr_policy);
1365 if (!strcmp(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]) ||
1366 (!strcmp(hdr_policy, AMDV_POLICY_FORCE_MODE) && !strcmp(hdr_force_mode, FORCE_HDR10))) {
1367 sprintf(dvstatus, "%d", 0);
1368 } else {
leng.fangd8ab2872024-06-28 16:23:43 +08001369 sprintf(dvstatus, "%d", mSceneOutInfo.amdv_type);
leng.fang91856072024-06-07 14:12:54 +08001370 }
1371 setBootEnv(UBOOTENV_DOLBYSTATUS, dvstatus);
1372
1373 if (strlen(dvenable) > 0)
1374 setBootEnv(UBOOTENV_DV_ENABLE, dvenable);
1375
1376 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 +08001377 dvstatus, mSceneOutInfo.amdv_type, mDvInfo.amdv_enable, hdr_policy, hdr_force_mode);
leng.fang91856072024-06-07 14:12:54 +08001378
1379 } else {
1380 MESON_LOGI("MBOX is not support dv, dvstatus %s dv_type %d dv_enable %s\n",
leng.fangd8ab2872024-06-28 16:23:43 +08001381 dvstatus, mSceneOutInfo.amdv_type, mDvInfo.amdv_enable);
leng.fang91856072024-06-07 14:12:54 +08001382 }
1383
1384 MESON_LOGI("colorattr: %s, outputMode %s, cd %s, cs %s\n",
1385 colorAttr.c_str(), outputMode, colorDepth, colorSpace);
1386 }
1387}
1388
1389bool ModePolicy::updateEnv()
1390{
1391 if (mDisplayType == DISPLAY_TYPE_MBOX)
1392 saveHdmiParamToEnv();
1393 return true;
1394}
1395
1396void ModePolicy::enableDV(int DvMode) {
1397 if (isMboxSupportDV() == false) {
1398 MESON_LOGI("This platform is not support dv or has no dv ko");
1399 return;
1400 }
1401 MESON_LOGI("DvMode %d", DvMode);
1402
1403 strcpy(mDvInfo.amdv_enable, "1");
1404
1405 //if TV
1406 if (DISPLAY_TYPE_TV == mDisplayType) {
1407 setHdrMode(HDR_MODE_OFF);
1408 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FOLLOW_SINK);
1409 }
1410
1411 //if OTT
1412 char hdr_policy[MESON_MODE_LEN] = {0};
1413 getHdrStrategy(hdr_policy);
1414 if ((DISPLAY_TYPE_MBOX == mDisplayType) || (DISPLAY_TYPE_REPEATER == mDisplayType)) {
1415 switch (DvMode) {
1416 case AMDV_SET_ENABLE:
1417 MESON_LOGI("Dv set Mode [DV_RGB_444_8BIT]\n");
1418 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0");
1419 break;
1420 case AMDV_SET_ENABLE_LL_YUV:
1421 MESON_LOGI("Dv set Mode [LL_YCbCr_422_12BIT]\n");
1422 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0");
1423 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "1");
1424 break;
1425 case AMDV_SET_ENABLE_LL_RGB:
1426 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0");
1427 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "2");
1428 break;
1429 default:
1430 setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0");
1431 }
1432
1433 if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) {
1434 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
1435 if (isDVEnable()) {
1436 setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
1437 }
1438 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) {
1439 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
1440 if (isDVEnable()) {
1441 setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
1442 }
1443 } else if (strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) {
1444 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]);
1445 if (isDVEnable()) {
1446 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE);
1447 }
1448 }
1449 }
1450
1451 setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_ENABLE);
1452 if (strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) {
1453 char hdr_force_mode[MESON_MODE_LEN] = {0};
1454 gethdrforcemode(hdr_force_mode);
1455 if (strstr(hdr_force_mode, FORCE_AMDV)) {
1456 setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_AMDV);
1457 } else if (strstr(hdr_force_mode, FORCE_HDR10)) {
1458 setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_HDR10);
1459 } else if (strstr(hdr_force_mode, AMDV_DISABLE_FORCE_SDR)) {
1460 // 8bit or not
1461 std::string cur_ColorAttribute;
1462 getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute);
1463 if (cur_ColorAttribute.find("8bit", 0) != std::string::npos) {
1464 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_8BIT);
1465 } else {
1466 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_10BIT);
1467 }
1468 }
1469 } else {
1470 int amdv_prop = DvMode == AMDV_SET_ENABLE_LL_YUV ? 1 : 0;
1471 setDisplayAttribute(DISPLAY_AMDV_MODE, to_string(amdv_prop));
1472 }
1473
1474 if (DISPLAY_TYPE_TV == mDisplayType) {
1475 setHdrMode(HDR_MODE_AUTO);
1476 }
1477
1478 initGraphicsPriority();
1479}
1480
1481void ModePolicy::disableDV(int DvMode) {
1482 //char tvmode[MESON_MODE_LEN] = {0};
1483 int check_status_count = 0;
1484 [[maybe_unused]] int amdv_type = DvMode;
1485
1486 MESON_LOGI("amdv_type %d", amdv_type);
1487 strcpy(mDvInfo.amdv_enable, "0");
1488
1489 //2. update sysfs
1490 char hdr_policy[MESON_MODE_LEN] = {0};
1491 getHdrStrategy(hdr_policy);
1492
1493 if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) {
1494 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
1495 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) {
1496 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
1497 }
1498
1499 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE);
1500 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_MODE_BYPASS);
1501 usleep(100000);//100ms
1502 std::string dvstatus = "";
1503 getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus);
1504
1505 if (strcmp(dvstatus.c_str(), BYPASS_PROCESS)) {
1506 while (++check_status_count <30) {
1507 usleep(20000);//20ms
1508 getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus);
1509 if (!strcmp(dvstatus.c_str(), BYPASS_PROCESS)) {
1510 break;
1511 }
1512 }
1513 }
1514
1515 MESON_LOGI("dvstatus %s, check_status_count [%d]", dvstatus.c_str(), check_status_count);
1516 setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_DISABLE);
1517
1518 if (DISPLAY_TYPE_TV == mDisplayType) {
1519 setHdrMode(HDR_MODE_AUTO);
1520 }
1521
1522 setSdrMode(SDR_MODE_AUTO);
1523}
1524
1525void ModePolicy::getPosition(const char* curMode, int *position) {
1526 char keyValue[20] = {0};
1527 char ubootvar[100] = {0};
1528 int defaultWidth = 0;
1529 int defaultHeight = 0;
1530 std::map<uint32_t, drm_mode_info_t> connecterModeList;
1531
1532 drm_mode_info_t mode = {
1533 "null",
1534 0, 0,
1535 0, 0,
1536 60.0,
1537 0
1538 };
1539
1540 if (mConnector->connection == DRM_MODE_CONNECTED) {
1541 getModes(mConnector, connecterModeList);
1542
1543 for (auto it = connecterModeList.begin(); it != connecterModeList.end(); it++) {
1544 if (mConnector->connector_type == DRM_MODE_CONNECTOR_TV) {
1545 if (strstr(curMode, it->second.name)) {
1546 strcpy(keyValue, curMode);
1547 mode = it->second;
1548 break;
1549 }
1550 } else {
1551 if (strstr(curMode, it->second.name)) {
1552 if (strstr(it->second.name, MODE_4K2KSMPTE_PREFIX)) {
1553 strcpy(keyValue, "4k2ksmpte");
1554 } else if (strstr(it->second.name, MODE_PANEL)) {
1555 strcpy(keyValue, MODE_PANEL);
1556 } else if (strchr(curMode,'p')) {
1557 strncpy(keyValue, curMode, strchr(curMode,'p') - curMode + 1);
1558 } else if (strchr(curMode,'i')){
1559 strncpy(keyValue, curMode, strchr(curMode,'i') - curMode + 1);
1560 }
1561 mode = it->second;
1562 break;
1563 }
1564 }
1565 }
1566 }
1567
1568 if (keyValue[0] != '0') {
1569 defaultWidth = mode.pixelW;
1570 defaultHeight = mode.pixelH;
1571 } else {
1572 strcpy(keyValue, MODE_1080P_PREFIX);
1573 defaultWidth = FULL_WIDTH_1080;
1574 defaultHeight = FULL_HEIGHT_1080;
1575 }
1576
1577 pthread_mutex_lock(&mEnvLock);
1578 sprintf(ubootvar, "ubootenv.var.%s_x", keyValue);
1579 position[0] = getBootenvInt(ubootvar, 0);
1580 sprintf(ubootvar, "ubootenv.var.%s_y", keyValue);
1581 position[1] = getBootenvInt(ubootvar, 0);
1582 sprintf(ubootvar, "ubootenv.var.%s_w", keyValue);
1583 position[2] = getBootenvInt(ubootvar, defaultWidth);
1584 sprintf(ubootvar, "ubootenv.var.%s_h", keyValue);
1585 position[3] = getBootenvInt(ubootvar, defaultHeight);
1586
1587 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]);
1588
1589 pthread_mutex_unlock(&mEnvLock);
1590
1591}
1592
1593void ModePolicy::setPosition(const char* curMode, int left, int top, int width, int height) {
1594 char x[512] = {0};
1595 char y[512] = {0};
1596 char w[512] = {0};
1597 char h[512] = {0};
1598 sprintf(x, "%d", left);
1599 sprintf(y, "%d", top);
1600 sprintf(w, "%d", width);
1601 sprintf(h, "%d", height);
1602
1603 MESON_LOGI("%s curMode:%s left:%d top:%d width:%d height:%d\n", __FUNCTION__, curMode, left, top, width, height);
1604
1605 char keyValue[20] = {0};
1606 char ubootvar[100] = {0};
1607 bool find = false;
1608 std::map<uint32_t, drm_mode_info_t> connecterModeList;
1609
1610 if (mConnector->connection == DRM_MODE_CONNECTED) {
1611 getModes(mConnector, connecterModeList);
1612
1613 for (auto it = connecterModeList.begin(); it != connecterModeList.end(); it++) {
1614 if (mConnector->connector_type == DRM_MODE_CONNECTOR_TV) {
1615 if (strstr(curMode, it->second.name)) {
1616 strcpy(keyValue, curMode);
1617 find = true;
1618 break;
1619 }
1620 } else {
1621 if (strstr(curMode, it->second.name)) {
1622 if (strstr(it->second.name, MODE_4K2KSMPTE_PREFIX)) {
1623 strcpy(keyValue, "4k2ksmpte");
1624 find = true;
1625 } else if (strstr(it->second.name, MODE_PANEL)) {
1626 strcpy(keyValue, MODE_PANEL);
1627 find = true;
1628 } else if (strchr(curMode,'p')) {
1629 strncpy(keyValue, curMode, strchr(curMode,'p') - curMode + 1);
1630 find = true;
1631 } else if (strchr(curMode,'i')){
1632 strncpy(keyValue, curMode, strchr(curMode,'i') - curMode + 1);
1633 find = true;
1634 }
1635 break;
1636 }
1637 }
1638 }
1639 }
1640
1641 if (!find)
1642 return;
1643
1644 mAdapter->setDisplayRect(left, top, width , height);
1645}
1646
1647void ModePolicy::setDigitalMode(const char* mode) {
1648 if (mode == NULL) return;
1649
1650 if (!strcmp("PCM", mode)) {
1651 sysfs_set_string(AUDIO_DSP_DIGITAL_RAW, "0");
1652 sysfs_set_string(AV_HDMI_CONFIG, "audio_on");
1653 } else if (!strcmp("SPDIF passthrough", mode)) {
1654 sysfs_set_string(AUDIO_DSP_DIGITAL_RAW, "1");
1655 sysfs_set_string(AV_HDMI_CONFIG, "audio_on");
1656 } else if (!strcmp("HDMI passthrough", mode)) {
1657 sysfs_set_string(AUDIO_DSP_DIGITAL_RAW, "2");
1658 sysfs_set_string(AV_HDMI_CONFIG, "audio_on");
1659 }
1660}
1661
1662bool ModePolicy::getDisplayMode(char* mode) {
1663 bool ret = false;
1664
1665 if (mode != NULL) {
1666 ret = mAdapter->getDisplayMode(mode);
1667 MESON_LOGI("%s mode:%s\n", __FUNCTION__, mode);
1668 } else {
1669 MESON_LOGE("%s mode is NULL\n", __FUNCTION__);
1670 }
1671
1672 return ret;
1673}
1674
1675//set hdmi output mode
1676int32_t ModePolicy::setDisplayMode(std::string &mode) {
1677 MESON_LOGI("%s mode:%s\n", __FUNCTION__, mode.c_str());
1678 mAdapter->setDisplayMode(mode);
1679 return 0;
1680}
1681
1682int32_t ModePolicy::setDisplayMode(const char *mode) {
1683 if (!mode) {
1684 MESON_LOGE("ModePolicy::setDisplayMode null mode");
1685 return -EINVAL;
1686 }
1687 std::string displayMode(mode);
1688 return setDisplayMode(displayMode);
1689}
1690
1691bool ModePolicy::setDisplayAttribute(const std::string cmd, const std::string attribute) {
1692 return mAdapter->setDisplayAttribute(cmd, attribute);
1693}
1694bool ModePolicy::getDisplayAttribute(const std::string cmd, std::string& attribute) {
1695 return mAdapter->getDisplayAttribute(cmd, attribute);
1696}
1697
1698bool ModePolicy::isMatchMode(char* curmode, const char* outputmode) {
1699 bool ret = false;
1700 char tmpMode[MESON_MODE_LEN] = {0};
1701
1702 char *pCmp = curmode;
1703 //check line feed key
1704 char *pos = strchr(pCmp, 0x0a);
1705 if (NULL == pos) {
1706 //check return key
1707 char *pos = strchr(pCmp, 0x0d);
1708 if (NULL == pos) {
1709 strcpy(tmpMode, pCmp);
1710 } else {
1711 strncpy(tmpMode, pCmp, pos - pCmp);
1712 }
1713 } else {
1714 strncpy(tmpMode, pCmp, pos - pCmp);
1715 }
1716
1717 MESON_LOGI("curmode:%s, tmpMode:%s, outputmode:%s\n", curmode, tmpMode, outputmode);
1718
1719 if (!strcmp(tmpMode, outputmode)) {
1720 ret = true;
1721 }
1722
1723 return ret;
1724}
1725
1726bool ModePolicy::isTvSupportALLM() {
1727 char allm_mode_cap[PROP_VALUE_MAX];
1728 memset(allm_mode_cap, 0, PROP_VALUE_MAX);
1729 int ret = 0;
1730
1731 sysfs_get_string(AUTO_LOW_LATENCY_MODE_CAP, allm_mode_cap, PROP_VALUE_MAX);
1732
1733 for (int i = 0; i < ARRAY_SIZE(ALLM_MODE_CAP); i++) {
1734 if (!strncmp(allm_mode_cap, ALLM_MODE_CAP[i], strlen(ALLM_MODE_CAP[i]))) {
1735 ret = i;
1736 }
1737 }
1738
1739 return (ret == 1) ? true : false;
1740}
1741
1742bool ModePolicy::getContentTypeSupport(const char* type) {
1743 char content_type_cap[MESON_MAX_STR_LEN] = {0};
1744 sysfs_get_string(HDMI_CONTENT_TYPE_CAP, content_type_cap, MESON_MAX_STR_LEN);
1745 if (strstr(content_type_cap, type)) {
1746 MESON_LOGI("getContentTypeSupport: %s is true", type);
1747 return true;
1748 }
1749
1750 MESON_LOGI("getContentTypeSupport: %s is false", type);
1751 return false;
1752}
1753
1754bool ModePolicy::getGameContentTypeSupport() {
1755 return getContentTypeSupport(CONTENT_TYPE_CAP[3]);
1756}
1757
1758bool ModePolicy::getSupportALLMContentTypeList(std::vector<std::string> *supportModes) {
1759 if (isTvSupportALLM()) {
1760 (*supportModes).push_back(std::string("allm"));
1761 }
1762
1763 for (int i = 0; i < ARRAY_SIZE(CONTENT_TYPE_CAP); i++) {
1764 if (getContentTypeSupport(CONTENT_TYPE_CAP[i])) {
1765 (*supportModes).push_back(std::string(CONTENT_TYPE_CAP[i]));
1766 }
1767 }
1768
1769 return true;
1770}
1771
1772
1773void ModePolicy::setTvDVEnable() {
1774 //if TV
1775 setHdrMode(HDR_MODE_OFF);
1776 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FOLLOW_SINK);
1777
1778 usleep(100000);//100ms
1779 setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_ENABLE);
1780 usleep(100000);//100ms
1781
1782 setHdrMode(HDR_MODE_AUTO);
1783
1784 initGraphicsPriority();
1785}
1786
1787void ModePolicy::setTvDVDisable() {
1788 int check_status_count = 0;
1789
1790 //2. update sysfs
1791 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
1792
1793 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE);
1794 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_MODE_BYPASS);
1795 usleep(100000);//100ms
1796 std::string dvstatus = "";
1797 getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus);
1798
1799 if (strcmp(dvstatus.c_str(), BYPASS_PROCESS)) {
1800 while (++check_status_count <30) {
1801 usleep(20000);//20ms
1802 getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus);
1803 if (!strcmp(dvstatus.c_str(), BYPASS_PROCESS)) {
1804 break;
1805 }
1806 }
1807 }
1808
1809 MESON_LOGI("dvstatus %s, check_status_count [%d]", dvstatus.c_str(), check_status_count);
1810 setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_DISABLE);
1811
1812 setHdrMode(HDR_MODE_AUTO);
1813 setSdrMode(SDR_MODE_AUTO);
1814}
1815
1816
1817int32_t ModePolicy::setDvMode(std::string &amdv_mode) {
1818 MESON_LOGI("%s dv mode:%s", __FUNCTION__, amdv_mode.c_str());
1819
1820 if (DISPLAY_TYPE_TV == mDisplayType) {
1821 //1. update prop
1822 strcpy(mConData.hdr_info.ubootenv_dv_type, amdv_mode.c_str());
1823
1824 //2. apply to driver
1825 if (strstr(amdv_mode.c_str(), "0")) {
1826 strcpy(mDvInfo.amdv_enable, "0");
1827 setTvDVDisable();
1828 } else {
1829 strcpy(mDvInfo.amdv_enable, "1");
1830 setTvDVEnable();
1831 }
1832
1833 //3. save env
1834 setBootEnv(UBOOTENV_DV_ENABLE, mDvInfo.amdv_enable);
1835 } else {
1836 //1. update dv env
1837 strcpy(mConData.hdr_info.ubootenv_dv_type, amdv_mode.c_str());
1838
1839 if (strstr(amdv_mode.c_str(), "0")) {
1840 strcpy(mDvInfo.amdv_enable, "0");
1841 } else {
1842 strcpy(mDvInfo.amdv_enable, "1");
1843 }
1844
1845 //Save user prefer dv mode only user change dv through UI
1846 setBootEnv(UBOOTENV_USER_DV_TYPE, mConData.hdr_info.ubootenv_dv_type);
1847 setBootEnv(UBOOTENV_DV_ENABLE, mDvInfo.amdv_enable);
1848 setBootEnv(UBOOTENV_DOLBYSTATUS, amdv_mode.c_str());
1849
1850 //2. set hdmi mode for trigger setting
1851 setSourceOutputMode(mCurrentMode);
1852 }
1853
1854 return 0;
1855}
1856
1857
1858/* *
1859 * @Description: this is a temporary solution, should be revert when android.hardware.graphics.composer@2.4 finished
1860 * set the ALLM_Mode
1861 * @params: "0": ALLM disable (VSIF still contain allm info)
1862 * "1": ALLM enable
1863 * "-1":really disable ALLM (VSIF don't contain allm info)
1864 * */
1865void ModePolicy::setALLMMode(int state) {
1866 /***************************************************************
1867 * Comment for special solution in this func *
1868 ***************************************************************
1869 * *
1870 * In HDMI Standard only 0 to disable ALLM and 1 to enable ALLM*
1871 * but ALLM and DV share the same bit in VSIF *
1872 * it cause conflict *
1873 * *
1874 * So in amlogic special solution: *
1875 * we add -1 to *
1876 * 1: disable ALLM *
1877 * 2: clean ALLM info in VSIF conflict bit *
1878 * when user set 0 to ALLM *
1879 * we will force change 0 into -1 here *
1880 * *
1881 ***************************************************************/
1882
1883 if (!isTvSupportALLM()) {
1884 SYS_LOGI("setALLMMode: TV not support ALLM\n");
1885 return;
1886 }
1887
1888 int perState = -1;
1889 char cur_allm_state[MESON_MODE_LEN] = {0};
1890 sysfs_get_string(AUTO_LOW_LATENCY_MODE, cur_allm_state, MESON_MODE_LEN);
1891 perState = atoi(cur_allm_state);
1892 if (perState == state) {
1893 SYS_LOGI("setALLMMode: the ALLM_Mode is not changed :%d\n", state);
1894 return;
1895 }
1896
1897 bool isTVSupportDV = isTvSupportDV();
1898
1899 char ubootenv_amdv_enable[MESON_MODE_LEN] = {0};
1900 std::string cur_ColorAttribute;
1901 char ubootenv_amdv_type[MESON_MODE_LEN] = {0};
1902 bool ret = false;
1903
1904 switch (state) {
1905 case -1:
1906 [[fallthrough]];
1907 case 0:
1908 //1. disable allm
1909 sysfs_set_string(AUTO_LOW_LATENCY_MODE, ALLM_MODE[0]);
1910 MESON_LOGI("setALLMMode: ALLM_Mode: %s", ALLM_MODE[0]);
1911 //2.1 get dv status before enable allm
1912 getBootEnv(UBOOTENV_DV_ENABLE, ubootenv_amdv_enable);
1913 //2.2 get current hdmi output resolution
1914 getDisplayMode(mCurrentMode);
1915 //2.3 get current hdmi output color space
1916 getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute);
1917 //2.4 get dv type before enable allm
1918 ret = getBootEnv(UBOOTENV_USER_DV_TYPE, ubootenv_amdv_type);
1919 //3 enable dv
1920 //when TV and current resolution support dv and dv is enable before enable allm
1921 if (isTVSupportDV
1922 && !strcmp(ubootenv_amdv_enable, "1")
1923 && !(meson_mode_support_mode(mModeConType, MESON_DOLBY_VISION_PRIORITY, mCurrentMode))) {
1924 // restore doblyvision when set -1/0 to ALLM
1925 if (!ret) {
1926 //best dv policy:sink-led -->source led
1927 if (strstr(mConData.hdr_info.dv_deepcolor, "DV_RGB_444_8BIT") != NULL
1928 && strstr(cur_ColorAttribute.c_str(), "444,8bit") != NULL) {
1929 enableDV(AMDV_SET_ENABLE);
leng.fangd8ab2872024-06-28 16:23:43 +08001930 mSceneOutInfo.amdv_type = AMDV_SET_ENABLE;
leng.fang91856072024-06-07 14:12:54 +08001931 } else if (strstr(mConData.hdr_info.dv_deepcolor, "LL_YCbCr_422_12BIT") != NULL
1932 && strstr(cur_ColorAttribute.c_str(), "422,12bit") != NULL) {
1933 enableDV(AMDV_SET_ENABLE_LL_YUV);
leng.fangd8ab2872024-06-28 16:23:43 +08001934 mSceneOutInfo.amdv_type = AMDV_SET_ENABLE_LL_YUV;
leng.fang91856072024-06-07 14:12:54 +08001935 } else {
1936 SYS_LOGI("can't enable dv for dv_deepcolor: %s and curColorAttribute: %s\n",
1937 mConData.hdr_info.dv_deepcolor, cur_ColorAttribute.c_str());
1938 }
1939 } else if (!strcmp(ubootenv_amdv_type, "2") && strstr(cur_ColorAttribute.c_str(), "422,12bit") != NULL) {
1940 enableDV(AMDV_SET_ENABLE_LL_YUV);
leng.fangd8ab2872024-06-28 16:23:43 +08001941 mSceneOutInfo.amdv_type = AMDV_SET_ENABLE_LL_YUV;
leng.fang91856072024-06-07 14:12:54 +08001942 } else if (!strcmp(ubootenv_amdv_type, "1") && strstr(cur_ColorAttribute.c_str(), "444,8bit") != NULL) {
1943 enableDV(AMDV_SET_ENABLE);
leng.fangd8ab2872024-06-28 16:23:43 +08001944 mSceneOutInfo.amdv_type = AMDV_SET_ENABLE;
leng.fang91856072024-06-07 14:12:54 +08001945 } else {
1946 SYS_LOGI("can't enable dv for curColorAttribute: %s\n", cur_ColorAttribute.c_str());
1947 }
1948 }
1949 break;
1950 case 1:
1951 //when TV support dv and dv is enable
1952 if (isTVSupportDV && isDVEnable()) {
leng.fangd8ab2872024-06-28 16:23:43 +08001953 mSceneOutInfo.amdv_type = AMDV_SET_DISABLE;
leng.fang91856072024-06-07 14:12:54 +08001954 // disable the doblyvision when ALLM enable
1955 disableDV(AMDV_SET_DISABLE);
1956 }
1957 //2. enable allm
1958 sysfs_set_string(AUTO_LOW_LATENCY_MODE, ALLM_MODE[2]);
1959 MESON_LOGI("setALLMMode: ALLM_Mode: %s", ALLM_MODE[2]);
1960 break;
1961 default:
1962 MESON_LOGE("setALLMMode: ALLM_Mode: error state[%d]", state);
1963 break;
1964 }
1965}
1966
1967bool ModePolicy::isTvConnector() {
1968 auto type = mConnector->connector_type;
1969 if (type == DRM_MODE_CONNECTOR_MESON_LVDS_A || type == DRM_MODE_CONNECTOR_MESON_LVDS_B ||
1970 type == DRM_MODE_CONNECTOR_MESON_LVDS_C || type == DRM_MODE_CONNECTOR_MESON_VBYONE_A ||
1971 type == DRM_MODE_CONNECTOR_MESON_VBYONE_B || type == DRM_MODE_CONNECTOR_LVDS ||
1972 type == LEGACY_NON_DRM_CONNECTOR_PANEL)
1973 return true;
1974
1975 return false;
1976}
1977
1978int32_t ModePolicy::setAutoLowLatencyMode(bool enabled) {
1979 auto type = mConnector->connector_type;
1980 if (type == DRM_MODE_CONNECTOR_HDMIA) {
1981 if (!isTvSupportALLM()) {
1982 return -1;
1983 }
1984
1985 if (enabled) {
1986 sysfs_set_string(LOW_LATENCY, LOW_LATENCY_ENABLE);
1987 } else {
1988 sysfs_set_string(LOW_LATENCY, LOW_LATENCY_DISABLE);
1989 }
1990 setALLMMode(enabled);
1991 return 0;
1992 }
1993
1994 // do nothing for tv
1995 if (isTvConnector())
1996 return 0;
1997
1998 return -1;
1999}
2000
2001void ModePolicy::setAllowedHdrTypes(uint32_t allowedHdrTypes, bool isAuto, bool passThrough) {
2002 //Match content Dynamic range
2003 if (passThrough) {
2004 setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_MATCH_CONTENT]);
2005 }
2006 // force SDR when autoAllowedHdrTypes are empty on system-preferred conversion
2007 else if (allowedHdrTypes == 0 && isAuto) {
2008 uint32_t userHdrType = 0;
2009 userHdrType = userHdrType | (1 << HAL_HDR_AMDV);
2010 userHdrType = userHdrType | (1 << HAL_HDR_HDR10);
2011 userHdrType = userHdrType | (1 << HAL_HDR_HLG);
2012 userHdrType = userHdrType | (1 << DRM_INVALID);
2013 string keyValue = std::to_string(userHdrType);
2014 setBootEnv(UBOOTENV_USER_PREFERRED_HDR_TYPE, keyValue.c_str());
2015 setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_SYSTEM_PREFERRED]);
2016 return;
2017 } else {
2018 //bit0-bit4 for hdr type and 1 is disable 0 is enable
2019 uint32_t userHdrType = 0;
2020 userHdrType = userHdrType | (1 << HAL_HDR_AMDV);
2021 userHdrType = userHdrType | (1 << HAL_HDR_HDR10);
2022 userHdrType = userHdrType | (1 << HAL_HDR_HLG);
2023 userHdrType = userHdrType | (1 << DRM_INVALID);
2024 allowedHdrTypes ^= userHdrType;
2025 allowedHdrTypes &= userHdrType;
2026 string keyValue = std::to_string(allowedHdrTypes);
2027 setBootEnv(UBOOTENV_USER_PREFERRED_HDR_TYPE, keyValue.c_str());
2028 if (isAuto)
2029 setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_SYSTEM_PREFERRED]);
2030 else
2031 setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_FORCE]);
2032
2033 MESON_LOGD("%s AllowedHdrType %d isAuto %d keyValue %s \n", __func__, allowedHdrTypes, isAuto, keyValue.c_str());
2034 }
2035
2036 return;
2037}
2038
2039int32_t ModePolicy::getPreferredHdrConversionType(void) {
2040 int32_t outHdrConversionType = -1;
2041
2042 char auto_policy[MESON_MODE_LEN] = {0};
2043 memset(auto_policy, 0, MESON_MODE_LEN);
2044 getBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, auto_policy);
2045
2046 //Match content Dynamic range
2047 if (strstr(auto_policy, MESON_HDR_PREFERRED_POLICY[MESON_HDR_MATCH_CONTENT])) {
2048 mHdr_policy = MESON_HDR_POLICY_SOURCE;
2049 mHdr_priority = MESON_G_DV_HDR10_HLG;
2050 }
2051 //System-preferred conversion or Force conversion
2052 else {
2053 bool isAuto = true;
2054 if (strstr(auto_policy, MESON_HDR_PREFERRED_POLICY[MESON_HDR_FORCE])) {
2055 isAuto = false;
2056 }
2057
2058 char user_hdr_type[MESON_MODE_LEN] = {0};
2059 memset(user_hdr_type, 0, MESON_MODE_LEN);
2060 bool ret = getBootEnv(UBOOTENV_USER_PREFERRED_HDR_TYPE, user_hdr_type);
2061 int32_t allowedHdrType = atoi(user_hdr_type);
2062 if (ret) {
2063 allowedHdrType = atoi(user_hdr_type);
2064 } else {
2065 allowedHdrType = 0; //all hdr enable as default
2066 }
2067
2068 //force SDR when autoAllowedHdrTypes are empty on system-preferred conversion
2069 uint32_t userHdrType = 0;
2070 userHdrType = userHdrType | (1 << HAL_HDR_AMDV);
2071 userHdrType = userHdrType | (1 << HAL_HDR_HDR10);
2072 userHdrType = userHdrType | (1 << HAL_HDR_HLG);
2073 userHdrType = userHdrType | (1 << DRM_INVALID);
2074 string keyValue = std::to_string(userHdrType);
2075 if (isAuto && strstr (user_hdr_type, keyValue.c_str())) {
2076 mHdr_priority = MESON_G_SDR;
2077 outHdrConversionType = DRM_INVALID;
2078 } else {
2079 bool containDVType = false, containHDR10Type = false,
2080 containHLGType = false, containSDRType = false;
2081
2082 MESON_LOGD("allowedHdrType 0x%x ", allowedHdrType);
2083 if (!(allowedHdrType & (1 << HAL_HDR_AMDV)))
2084 containDVType = true;
2085 if (!(allowedHdrType & (1 << HAL_HDR_HDR10)))
2086 containHDR10Type = true;
2087 if (!(allowedHdrType & (1 << HAL_HDR_HLG)))
2088 containHLGType = true;
2089 if (!(allowedHdrType & (1 << DRM_INVALID)))
2090 containSDRType = true;
2091
2092 drm_hdr_capabilities hdrCaps;
2093 getHdrCapabilities(&hdrCaps);
2094
2095 if (isAuto) {
2096 if (hdrCaps.DVSupported) {
2097 if (containHLGType && containHDR10Type && containDVType) {
2098 mHdr_policy = MESON_HDR_POLICY_SINK;
2099 mHdr_priority = MESON_G_DV_HDR10_HLG;
2100 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2101 } else if (containHDR10Type && containDVType) {
2102 mHdr_policy = MESON_HDR_POLICY_SINK;
2103 mHdr_priority = MESON_G_DV_HDR10;
2104 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2105 } else if (containHLGType && containDVType) {
2106 mHdr_policy = MESON_HDR_POLICY_SINK;
2107 mHdr_priority = MESON_G_DV_HLG;
2108 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2109 } else if (containHLGType && containHDR10Type) {
2110 mHdr_policy = MESON_HDR_POLICY_SINK;
2111 mHdr_priority = MESON_G_HDR10_HLG;
2112 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10);
2113 } else if (containDVType) {
2114 mHdr_policy = MESON_HDR_POLICY_SINK;
2115 mHdr_priority = MESON_G_DV;
2116 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2117 } else if (containHDR10Type) {
2118 mHdr_policy = MESON_HDR_POLICY_SINK;
2119 mHdr_priority = MESON_G_HDR10;
2120 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10);
2121 } else if (containHLGType) {
2122 mHdr_priority = MESON_G_HLG;
2123 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source due to dv can't HLG output
2124 } else {
2125 mHdr_policy = MESON_HDR_POLICY_SINK;
2126 mHdr_priority = MESON_G_SDR;
2127 outHdrConversionType = DRM_INVALID; //force sdr
2128 }
2129 } else {
2130 if (containHLGType && containHDR10Type) {
2131 mHdr_policy = MESON_HDR_POLICY_SINK;
2132 mHdr_priority = MESON_G_HDR10_HLG;
2133 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10);
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_policy = MESON_HDR_POLICY_SINK;
2140 mHdr_priority = MESON_G_HLG;
2141 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HLG);
2142 } else {
2143 mHdr_policy = MESON_HDR_POLICY_SINK;
2144 mHdr_priority = MESON_G_SDR;
2145 outHdrConversionType = DRM_INVALID; //force sdr
2146 }
2147 }
2148 } else {
2149 if (containDVType) {
2150 if (hdrCaps.DVSupported) {
2151 mHdr_policy = MESON_HDR_POLICY_SINK;
2152 mHdr_priority = MESON_G_DV;
2153 outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV);
2154 } else {
2155 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source
2156 mHdr_priority = MESON_G_DV_HDR10_HLG;
2157 }
2158 } else if (containHDR10Type) {
2159 if (hdrCaps.HDR10Supported) {
2160 mHdr_policy = MESON_HDR_POLICY_SINK;
2161 mHdr_priority = MESON_G_HDR10;
2162 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10);
2163 } else {
2164 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source
2165 mHdr_priority = MESON_G_DV_HDR10_HLG;
2166 }
2167 } else if (containHLGType) {
2168 if (hdrCaps.HLGSupported) {
2169 if (hdrCaps.DVSupported) {
2170 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source due to dv can't HLG output
2171 mHdr_priority = MESON_G_DV_HDR10_HLG;
2172 } else {
2173 mHdr_policy = MESON_HDR_POLICY_SINK;
2174 mHdr_priority = MESON_G_HLG;
2175 outHdrConversionType = static_cast<int32_t>(HAL_HDR_HLG);
2176 }
2177 } else {
2178 mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source
2179 mHdr_priority = MESON_G_DV_HDR10_HLG;
2180 }
2181 } else {
2182 mHdr_policy = MESON_HDR_POLICY_SINK;
2183 mHdr_priority = MESON_G_SDR;
2184 outHdrConversionType = DRM_INVALID; //force sdr
2185 }
2186 }
2187 }
2188 }
2189
2190 MESON_LOGD("hdr_policy:%d hdr_priority:0x%x outHdrConversionType:%d ", mHdr_policy, mHdr_priority, outHdrConversionType);
2191 return outHdrConversionType;
2192}
2193
2194int32_t ModePolicy::setHdrConversionPolicy(bool passthrough, int32_t forceType) {
2195 int32_t ret = 0;
2196 MESON_LOGD("%s passthrough %d forceType %d",
2197 __func__, passthrough, forceType);
2198
2199 if (passthrough || (forceType == -1)) {
2200 setBootEnv(UBOOTENV_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
2201
2202 char hdr_priority[MESON_MODE_LEN] = {0};
2203 sprintf(hdr_priority, "%d", mHdr_priority);
2204 setBootEnv(UBOOTENV_HDR_PRIORITY, hdr_priority);
2205 // set current hdmi mode
2206 getDisplayMode(mCurrentMode);
2207 setSourceOutputMode(mCurrentMode);
2208 } else {
2209 std::string type = FORCE_AMDV;
2210 meson_hdr_priority_e priority = MESON_DOLBY_VISION_PRIORITY;
2211 switch (forceType) {
2212 case DRM_AMDV: {
2213 priority = MESON_DOLBY_VISION_PRIORITY;
2214 type = FORCE_AMDV;
2215 break;
2216 }
2217 case DRM_HDR10:{
2218 priority = MESON_HDR10_PRIORITY;
2219 type = FORCE_HDR10;
2220 break;
2221 }
2222 case DRM_HLG:{
2223 priority = MESON_HDR10_PRIORITY;
2224 type = FORCE_HLG;
2225 break;
2226 }
2227 case DRM_INVALID: {
2228 priority = MESON_SDR_PRIORITY;
2229 type = AMDV_DISABLE_FORCE_SDR;
2230 break;
2231 }
2232 default:
2233 MESON_LOGE("setHdrConversionStrategy: error type[%d]", forceType);
2234 ret = -1;
2235 break;
2236 }
2237
2238 if (!ret) {
2239 getDisplayMode(mCurrentMode);
2240 meson_mode_set_policy_input(mModeConType, &mConData);
2241 if (!meson_mode_support_mode(mModeConType, priority, mCurrentMode)) {
2242 char hdr_policy[MESON_MODE_LEN] = {0};
2243 sprintf(hdr_policy, "%d", mHdr_policy);
2244 setBootEnv(UBOOTENV_HDR_POLICY, hdr_policy);
2245
2246 char hdr_priority[MESON_MODE_LEN] = {0};
2247 sprintf(hdr_priority, "%d", mHdr_priority);
2248 setBootEnv(UBOOTENV_HDR_PRIORITY, hdr_priority);
2249
2250 setSourceOutputMode(mCurrentMode);
2251 } else {
2252 MESON_LOGW("%s mode check failed\n", __func__);
2253 ret = -EINVAL;
2254 }
2255 }
2256 }
2257
2258 return ret;
2259}
2260
2261/*
2262* apply setting
2263*/
2264void ModePolicy::applyDisplaySetting(bool force) {
2265 //quiescent boot need not output
2266 bool quiescent = sys_get_bool_prop("ro_boot_quiescent", false);
2267
2268 MESON_LOGI("quiescent_mode is %d\n", quiescent);
2269 if (quiescent && (mState == OUTPUT_MODE_STATE_INIT)) {
2270 MESON_LOGI("don't need to setting hdmi when quiescent mode\n");
2271 return;
2272 }
2273
2274 //check cvbs mode
2275 bool cvbsMode = false;
2276
2277 if (!strcmp(mSceneOutInfo.displaymode, MODE_480CVBS) || !strcmp(mSceneOutInfo.displaymode, MODE_576CVBS)
2278 || !strcmp(mSceneOutInfo.displaymode, MODE_PAL_M) || !strcmp(mSceneOutInfo.displaymode, MODE_PAL_N)
2279 || !strcmp(mSceneOutInfo.displaymode, MODE_NTSC_M)
2280 || !strcmp(mSceneOutInfo.displaymode, "null") || !strcmp(mSceneOutInfo.displaymode, "dummy_l")
2281 || !strcmp(mSceneOutInfo.displaymode, MODE_PANEL)) {
2282 cvbsMode = true;
2283 }
2284
2285 /* not enable phy in systemcontrol by default
2286 * as phy will be enabled in driver when set mode
2287 * only enable phy if phy is disabled but not enabled
2288 */
2289 bool phy_enabled_already = true;
2290
2291 // 1. update hdmi frac_rate_policy
2292 char frac_rate_policy[MESON_MODE_LEN] = {0};
2293 char cur_frac_rate_policy[MESON_MODE_LEN] = {0};
2294 bool frac_rate_policy_change = false;
2295 std::string policy;
2296
2297 if (mReason != OUTPUT_CHANGE_BY_HWC) {
2298 getDisplayAttribute(DISPLAY_FRAC_RATE_POLICY, policy);
2299 strcpy(cur_frac_rate_policy, policy.c_str());
2300 getBootEnv(UBOOTENV_FRAC_RATE_POLICY, frac_rate_policy);
2301 if (strstr(frac_rate_policy, cur_frac_rate_policy) == NULL) {
2302 setDisplayAttribute(DISPLAY_FRAC_RATE_POLICY, frac_rate_policy);
2303 frac_rate_policy_change = true;
2304 } else {
2305 MESON_LOGI("cur frac_rate_policy is equals\n");
2306 }
2307 } else {
2308 getDisplayAttribute(DISPLAY_FRAC_RATE_POLICY, policy);
2309 strcpy(cur_frac_rate_policy, policy.c_str());
2310 char defVal[] = "2";
2311 sys_get_string_prop_default(HDMI_FRC_POLICY_PROP,frac_rate_policy, defVal);
2312 if (strstr(frac_rate_policy,"2")) {
2313 getBootEnv(UBOOTENV_FRAC_RATE_POLICY, frac_rate_policy);
2314 }
2315 MESON_LOGI("get frc policy from hwc is %s and current value is %s\n",frac_rate_policy, cur_frac_rate_policy);
2316 if (strstr(frac_rate_policy, cur_frac_rate_policy) == NULL) {
2317 frac_rate_policy_change = true;
2318 }
2319 }
2320
2321 // 2. set hdmi final color space
2322 char curColorAttribute[MESON_MODE_LEN] = {0};
2323 char final_deepcolor[MESON_MODE_LEN] = {0};
2324 bool attr_change = false;
2325
2326 std::string cur_ColorAttribute;
2327 getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute);
2328 strcpy(curColorAttribute, cur_ColorAttribute.c_str());
2329 strcpy(final_deepcolor, mSceneOutInfo.deepcolor);
2330 MESON_LOGI("curDeepcolor[%s] final_deepcolor[%s]\n", curColorAttribute, final_deepcolor);
2331
2332 if (strstr(curColorAttribute, final_deepcolor) == NULL) {
2333 MESON_LOGI("set color space from:%s to %s\n", curColorAttribute, final_deepcolor);
2334 // setDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, final_deepcolor);
2335 cur_ColorAttribute = final_deepcolor;
2336 attr_change = true;
2337 } else {
2338 MESON_LOGI("cur deepcolor is equals\n");
2339 }
2340
2341 // 3. update hdr strategy
2342 bool hdr_policy_change = false;
2343 std::string cur_hdr_policy;
2344 getDisplayAttribute(DISPLAY_HDR_POLICY, cur_hdr_policy);
2345 MESON_LOGI("cur hdr policy:%s\n", cur_hdr_policy.c_str());
2346
2347 std::string cur_hdr_force_mode;
2348 getDisplayAttribute(DISPLAY_FORCE_HDR_MODE, cur_hdr_force_mode);
2349 MESON_LOGI("cur hdr force mode:%s\n", cur_hdr_force_mode.c_str());
2350
2351 std::string cur_amdv_mode;
2352 getDisplayAttribute(DISPLAY_AMDV_MODE, cur_amdv_mode);
2353 MESON_LOGI("cur dv mode:%s\n", cur_amdv_mode.c_str());
2354
2355 std::string cur_amdv_policy;
2356 getDisplayAttribute(DISPLAY_AMDV_POLICY, cur_amdv_policy);
2357 MESON_LOGI("cur dv policy:%s\n", cur_amdv_policy.c_str());
2358
2359 char hdr_force_mode[MESON_MODE_LEN] = {0};
2360 gethdrforcemode(hdr_force_mode);
2361
2362 char hdr_policy[MESON_MODE_LEN] = {0};
2363 getHdrStrategy(hdr_policy);
2364
2365 if (!isDVEnable()) {
2366 if (strstr(cur_hdr_policy.c_str(), hdr_policy) == NULL) {
2367 MESON_LOGI("set hdr policy from:%s to %s\n", cur_hdr_policy.c_str(), hdr_policy);
2368 hdr_policy_change = true;
2369 } else if (!strcmp(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]) && (strstr(cur_hdr_force_mode.c_str(), hdr_force_mode) == NULL)) {
2370 MESON_LOGI("set hdr force mode from:%s to %s\n", cur_hdr_force_mode.c_str(), hdr_force_mode);
2371 hdr_policy_change = true;
2372 }
2373 } else {
2374 if (strstr(cur_amdv_policy.c_str(), hdr_policy) == NULL) {
2375 MESON_LOGI("set dv policy from:%s to %s\n", cur_amdv_policy.c_str(), hdr_policy);
2376 hdr_policy_change = true;
leng.fangd8ab2872024-06-28 16:23:43 +08002377 } else if ((mSceneOutInfo.amdv_type != AMDV_SET_DISABLE)
leng.fang91856072024-06-07 14:12:54 +08002378 && (!strcmp(hdr_policy, AMDV_POLICY_FORCE_MODE)
2379 && (strstr(cur_amdv_mode.c_str(), hdr_force_mode) == NULL))) {
2380 MESON_LOGI("set dv force mode from:%s to %s\n", cur_amdv_mode.c_str(), hdr_force_mode);
2381 hdr_policy_change = true;
2382 }
2383 }
2384
2385 //update hdr priority
2386 bool hdr_priority_change = false;
2387 meson_hdr_priority_e cur_hdr_priority;
2388 cur_hdr_priority = (meson_hdr_priority_e)getCurrentHdrPriority();
2389
2390 meson_hdr_priority_e hdr_priority;
2391 hdr_priority = (meson_hdr_priority_e)getHdrPriority();
2392
2393 if (cur_hdr_priority != hdr_priority) {
2394 SYS_LOGI("set hdr priority from:%x to %x\n", cur_hdr_priority, hdr_priority);
2395 hdr_priority_change = true;
2396 }
2397
2398 // 4. check dv
2399 int amdv_type = AMDV_SET_DISABLE;
2400 bool amdv_change = false;
2401
leng.fangd8ab2872024-06-28 16:23:43 +08002402 amdv_type = mSceneOutInfo.amdv_type;
leng.fang91856072024-06-07 14:12:54 +08002403 amdv_change = checkDVStatusChanged(amdv_type);
2404 if (isMboxSupportDV() && amdv_change && (hdr_priority == MESON_DOLBY_VISION_PRIORITY)) {
2405 //4.1 set avmute when signal change at boot
2406 if ((OUTPUT_MODE_STATE_INIT == mState)
2407 && (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]))) {
2408 // setDisplayAttribute(DISPLAY_HDMI_AVMUTE, "1");
2409 }
2410 //4.2 set dummy_l mode when dv change at UI switch
2411 if ((OUTPUT_MODE_STATE_SWITCH == mState) && amdv_change) {
2412 setDisplayMode("dummy_l");
2413 }
2414 //4.3 enable or disable dv core
2415 if (AMDV_SET_DISABLE != amdv_type) {
2416 enableDV(amdv_type);
2417 } else {
2418 disableDV(amdv_type);
2419 }
2420
2421 MESON_LOGI("isDVEnable: %d", isDVEnable());
2422 } else {
2423 amdv_change = false;
2424 MESON_LOGI("cur DvMode is equals\n");
2425 }
2426
2427 // 5. check hdmi output mode
2428 char final_displaymode[MESON_MODE_LEN] = {0};
2429 char curDisplayMode[MESON_MODE_LEN] = {0};
2430 bool modeChange = false;
2431
2432 getDisplayMode(curDisplayMode);
2433 strcpy(final_displaymode, mSceneOutInfo.displaymode);
2434 MESON_LOGI("curMode:[%s] ,final_displaymode[%s]\n", curDisplayMode, final_displaymode);
2435
2436 if (!isMatchMode(curDisplayMode, final_displaymode)) {
2437 modeChange = true;
2438 } else {
2439 MESON_LOGI("cur mode is equals\n");
2440 }
2441
2442 //6. check any change
2443 bool isNeedChange = false;
2444
2445 if (amdv_change || modeChange || attr_change || frac_rate_policy_change || hdr_policy_change || hdr_priority_change) {
2446 isNeedChange = true;
2447 } else if (force) {
2448 isNeedChange = true;
2449 MESON_LOGD("force changed");
2450 } else {
2451 MESON_LOGI("nothing need to be changed\n");
2452 }
2453
2454 // 8. set hdmi final output mode
2455 if (isNeedChange) {
2456 //apply hdr policy to driver sysfs
2457 if (hdr_policy_change) {
2458 if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) {
2459 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
2460 if (isDVEnable()) {
2461 setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
2462 }
2463 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) {
2464 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
2465 if (isDVEnable()) {
2466 setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
2467 }
2468 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]) || strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) {
2469 char hdr_force_mode[MESON_MODE_LEN] = {0};
2470 gethdrforcemode(hdr_force_mode);
2471 setDisplayAttribute(DISPLAY_FORCE_HDR_MODE, hdr_force_mode);
2472 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]);
2473 if (isDVEnable()) {
2474 setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE);
2475 if (strstr(hdr_force_mode, FORCE_AMDV)) {
2476 setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_AMDV);
2477 } else if (strstr(hdr_force_mode, FORCE_HDR10)) {
2478 setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_HDR10);
2479 } else if (strstr(hdr_force_mode, AMDV_DISABLE_FORCE_SDR)) {
2480 // 8bit or not
2481 // std::string cur_ColorAttribute;
2482 // getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute);
2483 if (cur_ColorAttribute.find("8bit", 0) != std::string::npos) {
2484 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_8BIT);
2485 } else {
2486 setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_10BIT);
2487 }
2488 }
2489 }
2490 }
2491 }
2492
leng.fang9cf09e22024-07-17 20:01:11 +08002493 if (attr_change || modeChange || frac_rate_policy_change || force)
leng.fang91856072024-06-07 14:12:54 +08002494 mAdapter->setColorAttribute(final_deepcolor);
2495
2496 //apply hdr priority to driver sysfs
2497 if (hdr_priority_change) {
2498 char tmp[MESON_MODE_LEN] = {0};
2499 sprintf(tmp, "%d", hdr_priority);
2500 setDisplayAttribute(DISPLAY_HDR_PRIORITY, tmp);
2501 }
2502
2503 //set hdmi mode
2504 setDisplayMode(final_displaymode);
limin.tiana9a091a2024-09-23 07:54:32 +00002505 setQMSVRR( curDisplayMode, final_displaymode );
2506
leng.fang91856072024-06-07 14:12:54 +08002507 /* phy already turned on after write display/mode node */
2508 phy_enabled_already = true;
2509 } else {
2510 MESON_LOGI("curDisplayMode is equal final_displaymode, Do not need set it\n");
2511 }
2512
2513 // graphic
2514 char final_Mode[MESON_MODE_LEN] = {0};
2515 getDisplayMode(final_Mode);
2516 char defVal[] = "0x0";
2517 if (sys_get_bool_prop(PROP_DISPLAY_SIZE_CHECK, true)) {
2518 char resolution[MESON_MODE_LEN] = {0};
2519 char defaultResolution[MESON_MODE_LEN] = {0};
2520 char finalResolution[MESON_MODE_LEN] = {0};
2521 int w = 0, h = 0, w1 =0, h1 = 0;
2522 sysfs_get_string(SYS_DISPLAY_RESOLUTION, resolution, MESON_MODE_LEN);
2523 sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal);
2524 sscanf(resolution, "%dx%d", &w, &h);
2525 sscanf(defaultResolution, "%dx%d", &w1, &h1);
2526 if ((w != w1) || (h != h1)) {
2527 if (strstr(final_displaymode, "null") && w1 != 0) {
2528 sprintf(finalResolution, "%dx%d", w1, h1);
2529 } else {
2530 sprintf(finalResolution, "%dx%d", w, h);
2531 }
2532 sys_set_prop(PROP_DISPLAY_SIZE, finalResolution);
2533 }
2534 }
2535 sys_set_prop(PROP_DISPLAY_ALLM, isTvSupportALLM() ? "1" : "0");
2536 sys_set_prop(PROP_DISPLAY_GAME, getGameContentTypeSupport() ? "1" : "0");
2537
2538 char defaultResolution[MESON_MODE_LEN] = {0};
2539 sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal);
2540 MESON_LOGI("set display-size:%s\n", defaultResolution);
2541
2542 int position[4] = { 0, 0, 0, 0 };//x,y,w,h
2543 getPosition(final_displaymode, position);
2544 setPosition(final_displaymode, position[0], position[1],position[2], position[3]);
2545
2546 //audio
2547 char value[MESON_MAX_STR_LEN] = {0};
2548 memset(value, 0, sizeof(0));
2549 getBootEnv(UBOOTENV_DIGITAUDIO, value);
2550 setDigitalMode(value);
2551}
2552
2553void ModePolicy::getFramebufferSize(int disp, uint32_t & width, uint32_t & height) {
2554 char uiMode[PROPERTY_VALUE_MAX] = {0};
2555 if (disp == 0) {
2556 /*primary display*/
2557 if (sys_get_string_prop_default("persist_vendor_hwc_ui_mode", uiMode, "1080") > 0) {
2558 if (!strncmp(uiMode, "720", 3)) {
2559 width = 1280;
2560 height = 720;
2561 } else if (!strncmp(uiMode, "1080", 4)) {
2562 width = 1920;
2563 height = 1080;
2564 } else {
2565 MESON_ASSERT(0, "%s: get not support mode [%s] from vendor.ui_mode",
2566 __func__, uiMode);
2567 }
2568 } else {
2569 width = 1920;
2570 height = 1080;
2571 }
2572 }
2573}
2574
2575int32_t ModePolicy::initialize() {
2576 uint32_t width = 1280;
2577 uint32_t height = 1080;
2578 char log_level[PROPERTY_VALUE_MAX] = { 0 };
2579
leng.fang3e8a4b52024-07-24 14:51:30 +08002580 sys_get_string_prop_default("WESTON_GL_MODE_POLICY_DEBUG", log_level, "2");
leng.fang91856072024-06-07 14:12:54 +08002581 g_activeLevel = atoi(log_level);
2582 mAdapter->setLogLevel(g_activeLevel);
2583
2584 bootenv_init();
2585 getFramebufferSize(mDisplayId, width, height);
2586 mDefaultUI = to_string(height);
2587
2588 mAdapter->initDisplayAttributeInfo(mCrtc, mConnector);
2589 updateHdrCaps();
2590 if (DISPLAY_TYPE_MBOX == mDisplayType) {
2591 // mTxAuth = std::make_shared<HDCPTxAuth>();
2592
2593 setSourceDisplay(OUTPUT_MODE_STATE_INIT);
limin.tiana0140a72024-10-12 07:28:49 +00002594 applyDisplaySetting(false);
leng.fang91856072024-06-07 14:12:54 +08002595 } else if (DISPLAY_TYPE_TV == mDisplayType) {
2596 setSinkDisplay(true);
2597 }
2598#if 0
2599 } else if (DISPLAY_TYPE_TABLET == mDisplayType) {
2600
2601 } else if (DISPLAY_TYPE_REPEATER == mDisplayType) {
2602 setSourceDisplay(OUTPUT_MODE_STATE_INIT);
2603 }
2604#endif
2605
2606 return 0;
2607}
2608
2609void ModePolicy::setSinkDisplay(bool initState) {
2610 char current_mode[MESON_MODE_LEN] = {0};
2611 char outputmode[MESON_MODE_LEN] = {0};
2612
2613 getDisplayMode(current_mode);
2614 getBootEnv(UBOOTENV_OUTPUTMODE, outputmode);
2615 MESON_LOGD("init tv display old outputmode:%s, outputmode:%s\n", current_mode, outputmode);
2616
2617 if (strlen(outputmode) == 0)
2618 strncpy(outputmode, mDefaultUI.c_str(), MESON_MODE_LEN-1);
2619
2620 setSinkOutputMode(outputmode, initState);
2621}
2622
2623void ModePolicy::setSinkOutputMode(const char* outputmode, bool initState) {
2624 [[maybe_unused]] bool sinkInitState = initState;
2625 MESON_LOGI("set sink output mode:%s, init state:%d\n", outputmode, sinkInitState);
2626
2627 //set output mode
2628 char curMode[MESON_MODE_LEN] = {0};
2629 getDisplayMode(curMode);
2630
2631 MESON_LOGI("curMode = %s outputmode = %s", curMode, outputmode);
2632 if (strstr(curMode, outputmode) == NULL) {
2633 setDisplayMode(outputmode);
2634 }
2635
2636 char defVal[PROPERTY_VALUE_MAX] = "0x0";
2637 if (sys_get_bool_prop(PROP_DISPLAY_SIZE_CHECK, true)) {
2638 char resolution[MESON_MODE_LEN] = {0};
2639 char defaultResolution[MESON_MODE_LEN] = {0};
2640 char finalResolution[MESON_MODE_LEN] = {0};
2641 int w = 0, h = 0, w1 =0, h1 = 0;
2642 sysfs_get_string(SYS_DISPLAY_RESOLUTION, resolution, MESON_MODE_LEN);
2643
2644 sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal);
2645 sscanf(resolution, "%dx%d", &w, &h);
2646 sscanf(defaultResolution, "%dx%d", &w1, &h1);
2647 if ((w != w1) || (h != h1)) {
2648 if (strstr(outputmode, "null") && w1 != 0) {
2649 sprintf(finalResolution, "%dx%d", w1, h1);
2650 } else {
2651 sprintf(finalResolution, "%dx%d", w, h);
2652 }
2653 sys_set_prop(PROP_AMDV_PRIORITY, finalResolution);
2654 }
2655 }
2656
2657 char defaultResolution[MESON_MODE_LEN] = {0};
2658 sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal);
2659 MESON_LOGI("set display-size:%s\n", defaultResolution);
2660
2661 //update hwc windows size
2662 int position[4] = { 0, 0, 0, 0 };//x,y,w,h
2663 getPosition(outputmode, position);
2664 setPosition(outputmode, position[0], position[1],position[2], position[3]);
2665
2666 //update hdr policy
2667 if ((isMboxSupportDV() == false)) {
2668 if (sys_get_bool_prop(PROP_AMDV_FEATURE, false)) {
2669 char hdr_policy[MESON_MODE_LEN] = {0};
2670 getHdrStrategy(hdr_policy);
2671 if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) {
2672 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]);
2673 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) {
2674 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]);
2675 } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE])) {
2676 setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]);
2677 }
2678 } else {
2679 initHdrSdrMode();
2680 }
2681 }
2682
2683 if (isMboxSupportDV()) {
2684 if (isTvDVEnable()) {
2685 setTvDVEnable();
2686 } else {
2687 setTvDVDisable();
2688 }
2689 }
2690
2691 //audio
2692 char value[MESON_MAX_STR_LEN] = {0};
2693 memset(value, 0, sizeof(0));
2694 getBootEnv(UBOOTENV_DIGITAUDIO, value);
2695 setDigitalMode(value);
2696
2697 //save output mode
2698 char finalMode[MESON_MODE_LEN] = {0};
2699 getDisplayMode(finalMode);
2700 if (DISPLAY_TYPE_TABLET != mDisplayType) {
2701 setBootEnv(UBOOTENV_OUTPUTMODE, (char *)finalMode);
2702 }
2703 if (strstr(finalMode, "cvbs") != NULL) {
2704 setBootEnv(UBOOTENV_CVBSMODE, (char *)finalMode);
2705 } else if (strstr(finalMode, "hz") != NULL) {
2706 setBootEnv(UBOOTENV_HDMIMODE, (char *)finalMode);
2707 }
2708
2709 MESON_LOGI("set output mode:%s done\n", finalMode);
2710}
2711
2712bool ModePolicy::isHdmiUsed() {
2713 bool ret = true;
2714 char hdmi_state[MESON_MODE_LEN] = {0};
2715
2716 sysfs_get_string(DISPLAY_HDMI_USED, hdmi_state, MESON_MODE_LEN);
2717
2718 if (strstr(hdmi_state, "1") == NULL) {
2719 ret = false;
2720 }
2721
2722 return ret;
2723}
2724
2725bool ModePolicy::isConnected() {
2726 bool ret = ((mConnectorType == CONN_TYPE_HDMI) &&
2727 (mConnector->connection == DRM_MODE_CONNECTED));
2728 return ret;
2729}
2730
2731bool ModePolicy::isVMXCertification() {
2732 return sys_get_bool_prop(PROP_VMX, false);
2733}
2734
2735bool ModePolicy::isHdmiEdidParseOK() {
2736 bool ret = true;
2737
2738 char edidParsing[MESON_MODE_LEN] = {0};
2739 sysfs_get_string(DISPLAY_EDID_STATUS, edidParsing, MESON_MODE_LEN);
2740
2741 if (strcmp(edidParsing, "ok")) {
2742 ret = false;
2743 }
2744
2745 return ret;
2746}
2747
2748bool ModePolicy::isBestPolicy() {
2749 char isBestMode[MESON_MODE_LEN] = {0};
2750 if (DISPLAY_TYPE_TV == mDisplayType) {
2751 return false;
2752 }
2753
2754 return !getBootEnv(UBOOTENV_ISBESTMODE, isBestMode) || strcmp(isBestMode, "true") == 0;
2755}
2756
2757bool ModePolicy::isBestColorSpace() {
2758 bool ret = false;
2759 char user_colorattr[MESON_MODE_LEN] = {0};
2760 if (DISPLAY_TYPE_TV == mDisplayType) {
2761 return false;
2762 }
2763
2764 ret = getBootEnv(UBOOTENV_USER_COLORATTRIBUTE, user_colorattr);
2765
2766 if (!ret) {
2767 return true;
2768 } else if (strstr(user_colorattr, "bit") == NULL) {
2769 return true;
2770 }
2771
2772 return false;
2773}
2774
2775void ModePolicy::setDefaultMode() {
2776 MESON_LOGE("EDID parsing error detected\n");
2777
2778 // check hdmi output mode
2779 char curDisplayMode[MESON_MODE_LEN] = {0};
2780 getDisplayMode(curDisplayMode);
2781
2782 if (!isMatchMode(curDisplayMode, MESON_DEFAULT_HDMI_MODE)) {
2783 //set default color format
2784 setDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, MESON_DEFAULT_COLOR_FORMAT);
2785 //set default resolution
2786 setDisplayMode(MESON_DEFAULT_HDMI_MODE);
2787
2788 //update display position
2789 int position[4] = { 0, 0, 0, 0 };//x,y,w,h
2790 getPosition(MESON_DEFAULT_HDMI_MODE, position);
2791 setPosition(MESON_DEFAULT_HDMI_MODE, position[0], position[1],position[2], position[3]);
2792 } else {
2793 MESON_LOGI("cur mode is default mode\n");
2794 }
2795}
2796
leng.fang3c0ab6d2024-08-01 16:29:00 +08002797void ModePolicy::setDisplay(output_mode_state state)
2798{
2799 if ((state == OUTPUT_MODE_STATE_INIT) ||
2800 (state == OUTPUT_MODE_STATE_POWER)) {
2801 memset(&mConData, 0, sizeof(meson_policy_in));
2802 memset(&mDvInfo, 0, sizeof(hdmi_amdv_info_t));
2803 mState = state;
2804 mConData.state = static_cast<meson_mode_state>(state);
leng.fang91856072024-06-07 14:12:54 +08002805
leng.fang3c0ab6d2024-08-01 16:29:00 +08002806 getConnectorData(&mConData, &mDvInfo);
2807 if (isTvSupportDV() && isMboxSupportDV()) {
2808 strcpy(mDvInfo.amdv_enable, "1");
2809 mConData.hdr_info.is_amdv_enable = isDVEnable();
2810 }
2811
2812 strcpy(mConData.cur_displaymode, mConData.con_info.ubootenv_hdmimode);
2813 }
2814
2815 // TOD sceneProcess
2816 if (isBestPolicy()) {
2817 if (state == OUTPUT_MODE_STATE_INIT || mPolicy == MESON_POLICY_INVALID) {
2818 mPolicy = MESON_POLICY_MIX;
2819 }
2820 } else {
2821 mPolicy = MESON_POLICY_INVALID;
2822 }
2823
2824 meson_mode_set_policy(mModeConType, mPolicy);
2825 meson_mode_set_policy_input(mModeConType, &mConData);
2826 meson_mode_get_policy_output(mModeConType, &mSceneOutInfo);
2827
2828 //5. apply settings to driver
2829 applyDisplaySetting(state == OUTPUT_MODE_STATE_POWER);
2830}
leng.fang91856072024-06-07 14:12:54 +08002831/*
2832 * OUTPUT_MODE_STATE_INIT for boot
2833 * OUTPUT_MODE_STATE_POWER for hdmi plug and suspend/resume
2834 */
2835void ModePolicy::setSourceDisplay(output_mode_state state) {
2836 std::lock_guard<std::mutex> lock(mMutex);
2837
2838 //1. hdmi used and hpd = 0
2839 //set dummy_l mode
2840 if ((isHdmiUsed() == true) && (isConnected() == false)) {
leng.fang3c0ab6d2024-08-01 16:29:00 +08002841 MESON_LOGD("hdmi usd, set cvbs");
2842 setDisplay(state);
leng.fang91856072024-06-07 14:12:54 +08002843 MESON_LOGI("hdmi used but plugout when boot\n");
2844 return;
2845 }
2846
2847 //2. hdmi edid parse error and hpd = 1
2848 //set default reolsution and color format
2849 if ((isHdmiEdidParseOK() == false) &&
2850 (isConnected() == true)) {
2851 setDefaultMode();
2852 return;
2853 }
2854
2855 //3. update hdmi info when boot and hdmi plug/suspend/resume
2856 if ((state == OUTPUT_MODE_STATE_INIT) ||
2857 (state == OUTPUT_MODE_STATE_POWER)) {
2858 memset(&mConData, 0, sizeof(meson_policy_in));
2859 memset(&mDvInfo, 0, sizeof(hdmi_amdv_info_t));
2860 mState = state;
2861 mConData.state = static_cast<meson_mode_state>(state);
2862
2863 getConnectorData(&mConData, &mDvInfo);
2864 if (isTvSupportDV() && isMboxSupportDV()) {
2865 strcpy(mDvInfo.amdv_enable, "1");
2866 mConData.hdr_info.is_amdv_enable = isDVEnable();
2867 }
2868
2869 strcpy(mConData.cur_displaymode, mConData.con_info.ubootenv_hdmimode);
2870 }
2871
2872 // TOD sceneProcess
2873 if (isBestPolicy()) {
2874 if (state == OUTPUT_MODE_STATE_INIT || mPolicy == MESON_POLICY_INVALID) {
2875 mPolicy = MESON_POLICY_MIX;
2876 }
2877 } else {
2878 mPolicy = MESON_POLICY_INVALID;
2879 }
2880
2881 meson_mode_set_policy(mModeConType, mPolicy);
2882 meson_mode_set_policy_input(mModeConType, &mConData);
2883 meson_mode_get_policy_output(mModeConType, &mSceneOutInfo);
2884
leng.fang91856072024-06-07 14:12:54 +08002885}
2886
leng.fang5ec9b6c2024-07-29 14:25:00 +08002887void ModePolicy::setSourceOutputModeNoLock(const char* outputmode, bool force) {
leng.fang91856072024-06-07 14:12:54 +08002888 if (DISPLAY_TYPE_TV == mDisplayType) {
2889 setSinkOutputMode(outputmode, false);
2890 } else {
2891
2892 getConnectorUserData(&mConData, &mDvInfo);
2893
2894 getHdrUserInfo(&mConData.hdr_info);
2895
2896 mState = OUTPUT_MODE_STATE_SWITCH;
2897 mConData.state = static_cast<meson_mode_state>(mState);
2898
2899 strcpy(mConData.cur_displaymode, outputmode);
2900 meson_mode_set_policy_input(mModeConType, &mConData);
2901 meson_mode_get_policy_output(mModeConType, &mSceneOutInfo);
2902
2903 applyDisplaySetting(force);
2904 }
2905}
2906
leng.fang5ec9b6c2024-07-29 14:25:00 +08002907void ModePolicy::setSourceOutputMode(const char* outputmode, bool force) {
2908 std::lock_guard<std::mutex> lock(mMutex);
2909
2910 setSourceOutputModeNoLock(outputmode, force);
2911}
2912
leng.fang91856072024-06-07 14:12:54 +08002913void ModePolicy::getConnectorUserData(struct meson_policy_in* data, hdmi_amdv_info_t *dinfo) {
2914 if (!data || !dinfo) {
2915 MESON_LOGE("%s data is NULL\n", __FUNCTION__);
2916 return;
2917 }
2918
2919 bool ret = false;
2920
2921 //hdmi color space best policy flag
2922 data->con_info.is_bestcolorspace = isBestColorSpace();
2923
2924 MESON_LOGI("isbestColorspace:%d\n",
2925 data->con_info.is_bestcolorspace);
2926
2927 getDisplayMode(mCurrentMode);
2928 ret = getBootEnv(UBOOTENV_HDMIMODE, data->con_info.ubootenv_hdmimode);
2929 if (!ret) {
2930 //if env is null,use none as default value
2931 strcpy(data->con_info.ubootenv_hdmimode, "none");
2932 }
2933 getBootEnv(UBOOTENV_CVBSMODE, data->con_info.ubootenv_cvbsmode);
2934 MESON_LOGI("hdmi_current_mode:%s, ubootenv hdmimode:%s cvbsmode:%s\n",
2935 mCurrentMode,
2936 data->con_info.ubootenv_hdmimode,
2937 data->con_info.ubootenv_cvbsmode);
2938
2939 ret = getBootEnv(UBOOTENV_USER_COLORATTRIBUTE, data->con_info.ubootenv_colorattr);
2940 if (!ret) {
2941 //if env is null,use none as default value
2942 strcpy(data->con_info.ubootenv_colorattr, "none");
2943 }
2944 MESON_LOGI("ubootenv_colorattribute:%s\n",
2945 data->con_info.ubootenv_colorattr);
2946
2947 //if no dolby_status env set to std for enable dv
2948 //if box support dv
2949 char amdv_enable[MESON_MODE_LEN];
2950 ret = getBootEnv(UBOOTENV_DV_ENABLE, amdv_enable);
2951 if (ret) {
2952 strcpy(dinfo->amdv_enable, amdv_enable);
2953 } else if (isMboxSupportDV()) {
2954 strcpy(dinfo->amdv_enable, "1");
2955 } else {
2956 strcpy(dinfo->amdv_enable, "0");
2957 }
2958 MESON_LOGI("dv_enable:%s\n", dinfo->amdv_enable);
2959
2960 char ubootenv_amdv_type[MESON_MODE_LEN];
2961 ret = getBootEnv(UBOOTENV_USER_DV_TYPE, ubootenv_amdv_type);
2962 if (ret) {
2963 strcpy(dinfo->ubootenv_amdv_type, ubootenv_amdv_type);
2964 } else if (isMboxSupportDV()) {
2965 strcpy(dinfo->ubootenv_amdv_type, "1");
2966 } else {
2967 strcpy(dinfo->ubootenv_amdv_type, "0");
2968 }
2969 MESON_LOGI("ubootenv_dv_type:%s\n", dinfo->ubootenv_amdv_type);
2970}
2971
2972void ModePolicy::drmMode2MesonMode(meson_mode_info_t &mesonMode, drm_mode_info_t &drmMode) {
2973 strncpy(mesonMode.name, drmMode.name, MESON_MODE_LEN);
2974 mesonMode.dpi_x = drmMode.dpiX;
2975 mesonMode.dpi_y = drmMode.dpiY;
2976 mesonMode.pixel_w = drmMode.pixelW;
2977 mesonMode.pixel_h = drmMode.pixelH;
2978 mesonMode.refresh_rate = drmMode.refreshRate;
2979 mesonMode.group_id = drmMode.groupId;
2980}
2981
2982void ModePolicy::getSupportedModes() {
2983 //pthread_mutex_lock(&mEnvLock);
2984 std::map<uint32_t, drm_mode_info_t> connecterModeList;
2985
2986 /* reset ModeList */
2987 mModes.clear();
2988 if (mConnector->connection == DRM_MODE_CONNECTED) {
2989 getModes(mConnector, connecterModeList);
2990
2991 for (auto it = connecterModeList.begin(); it != connecterModeList.end(); it++) {
2992 // All modes are supported
2993 if (isModeSupported(it->second)) {
2994 mModes.emplace(mModes.size(), it->second);
2995 }
2996 }
2997 }
2998
2999 /* transfer to meson_mode_info_t */
3000 auto conPtr = &mConData.con_info;
3001 conPtr->modes_size = mModes.size();
3002 if (conPtr->modes_size > conPtr->modes_capacity) {
3003 // realloc memory
3004 void * buff = realloc(conPtr->modes, conPtr->modes_size * sizeof(meson_mode_info_t));
3005 MESON_ASSERT(buff, "modePolicy realloc but has no memory");
3006 conPtr->modes = (meson_mode_info_t *) buff;
3007 conPtr->modes_capacity = conPtr->modes_size;
3008 }
3009
limin.tiana9a091a2024-09-23 07:54:32 +00003010 loadVrrModeGroups();
3011 groupDisplayModes();
3012
leng.fang91856072024-06-07 14:12:54 +08003013 int i = 0;
3014 for (auto it = mModes.begin(); it != mModes.end(); it++) {
3015 drmMode2MesonMode(conPtr->modes[i], it->second);
3016 i++;
3017 }
3018}
3019
3020bool ModePolicy::getModeNameForPix(char *name,
3021 int32_t width, int32_t height, uint32_t refresh, uint32_t flags)
3022{
3023 std::map<uint32_t, drm_mode_info_t> connecterModeList;
3024 drm_mode_info_t mode;
3025 int current_interlaced;
3026 bool ret = false;
3027
3028 if (!mConnector || mConnector->connection != DRM_MODE_CONNECTED)
3029 return false;
3030
3031 drmModeModeInfoPtr drmModes = mConnector->modes;
3032
3033 for (int i = 0;i < mConnector->count_modes; i++) {
3034 current_interlaced = (drmModes[i].flags & DRM_MODE_FLAG_INTERLACE);
3035 if (drmModes[i].hdisplay == width && drmModes[i].vdisplay == height &&
3036 drmModes[i].vrefresh == refresh &&
3037 current_interlaced == (flags & DRM_MODE_FLAG_INTERLACE)) {
3038 strcpy(name, drmModes[i].name);
3039 ret = true;
3040 break;
3041 }
3042 }
3043 return ret;
3044}
3045
3046bool ModePolicy::isModeSupported(drm_mode_info_t mode) {
3047 bool ret = false;
3048 uint32_t i;
3049
3050 for (i = 0; i < ARRAY_SIZE(DISPLAY_MODE_LIST); i++) {
3051 if (!strcmp(DISPLAY_MODE_LIST[i], mode.name)) {
3052 ret = true;
3053 break;
3054 }
3055 }
3056
3057 return ret;
3058}
3059
limin.tiana9a091a2024-09-23 07:54:32 +00003060bool ModePolicy::isSeamlessMode(const drm_mode_info_t & mode, const drm_mode_info_t &groupMode)
3061{
3062 if (mHdrCapabilities.AMDV_4K30_Supported == 1) {
3063 if (mode.pixelW == FB_SIZE_4K_W && mode.pixelH == FB_SIZE_4K_H) {
3064 auto refreshA = ceilf(mode.refreshRate);
3065 auto refreshB = ceilf(groupMode.refreshRate);
3066 if ((refreshA > REFRESH_RATE_30 && refreshB <= REFRESH_RATE_30) ||
3067 (refreshA <= REFRESH_RATE_30 && refreshB > REFRESH_RATE_30)) {
3068 return false;
3069 }
3070 }
3071 }
3072
3073 for (int32_t i = 0; i < mVrrModeGroup.num; i++) {
3074 if (mVrrModeGroup.groups[i].width == mode.pixelW
3075 && mVrrModeGroup.groups[i].height == mode.pixelH) {
3076 if (((mode.refreshRate - mVrrModeGroup.groups[i].vrr_min) >= 0
3077 //frac refresh rate
3078 || std::abs(mode.refreshRate - (mVrrModeGroup.groups[i].vrr_min * 1000) / (float)1001) < 0.001)
3079 && (mode.refreshRate - mVrrModeGroup.groups[i].vrr_max <= 0)) {
3080 if (mVrrModeGroup.groups[i].width == groupMode.pixelW
3081 && mVrrModeGroup.groups[i].height == groupMode.pixelH) {
3082 if (((groupMode.refreshRate - mVrrModeGroup.groups[i].vrr_min) >= 0
3083 //frac refresh rate
3084 || std::abs(groupMode.refreshRate - (mVrrModeGroup.groups[i].vrr_min * 1000) / (float)1001) < 0.001)
3085 && (groupMode.refreshRate - mVrrModeGroup.groups[i].vrr_max <= 0)) {
3086 return true;
3087 } else {
3088 return false;
3089 }
3090 }
3091 }
3092 }
3093 }
3094 return false;
3095}
3096
3097bool ModePolicy::supportVrr()
3098{
3099 std::string vrr_cap;
3100 getDisplayAttribute(DISPLAY_VRR_SUPPORTED, vrr_cap);
3101 if (atoi(vrr_cap.c_str()) == 1)
3102 return true;
3103 return false;
3104}
3105
3106int32_t ModePolicy::loadVrrModeGroups()
3107{
3108 if (!(mDisplayType == DISPLAY_TYPE_TV)) {
3109 if (!(supportVrr()) || !mSeamlessSwitchEnabled) {
3110 return 0;
3111 }
3112 }
3113
3114 memset(&mVrrModeGroup, 0, sizeof(mVrrModeGroup));
3115 mVrrModeGroup.conn_id = mConnector->connector_id;
3116 auto ret = ioctl(mDrmFd, DRM_IOCTL_MESON_GET_VRR_RANGE, &mVrrModeGroup);
3117
3118 MESON_LOGD("\n %s %d conn_id:%d mDrmFd:%d mVrrModeGroup.num:%d\n",__FUNCTION__,__LINE__, mVrrModeGroup.conn_id, mDrmFd, mVrrModeGroup.num);
3119 if (ret) {
3120 MESON_LOGE("DRM_IOCTL_MESON_GET_VRR_RANGE error ret %d %s(%d)", ret, strerror(errno), errno);
3121 return -EINVAL;
3122 }
3123
3124 return 0;
3125}
3126
3127bool ModePolicy::isVrrGroupedMode(const drm_mode_info_t & mode)
3128{
3129 bool ret = true;
3130 int count = 0;
3131 drm_mode_info_t mesonMode = {
3132 .name = "INVALID_MODE",
3133 .dpiX = 0,
3134 .dpiY = 0,
3135 .pixelW = 0,
3136 .pixelH = 0,
3137 .refreshRate = 0,
3138 .groupId = 0,
3139 };
3140 for (auto it = mModes.begin(); it != mModes.end(); ++it) {
3141 MESON_LOGD("\n isVrrGroupedMode:mode name: %s mModes name:%s\n", mode.name, it->second.name);
3142 if (strncmp(it->second.name, mode.name, DRM_DISPLAY_MODE_LEN) == 0) {
3143 mesonMode = it->second;
3144 break;
3145 }
3146 }
3147 for (auto it = mModes.begin(); it != mModes.end(); ++it) {
3148 MESON_LOGD("\n isVrrGroupedMode:mode(%d %d) mModes(%d %d) group id:(%d %d)\n",
3149 mesonMode.pixelW, mesonMode.pixelH, it->second.pixelW, it->second.pixelH, mesonMode.groupId ,it->second.groupId);
3150 if (it->second.pixelW == mesonMode.pixelW && it->second.pixelH == mesonMode.pixelH
3151 && mesonMode.groupId == it->second.groupId) {
3152 count++;
3153 }
3154 }
3155 if (count <= 1)
3156 ret = false;
3157 return ret;
3158}
3159
3160int32_t ModePolicy::getDrmModeInfoFromName(char* name , drm_mode_info_t* drmMode)
3161{
3162 int ret = -1;
3163 if (!name || !drmMode) {
3164 MESON_LOGE("\n invalid parameter\n");
3165 return ret;
3166 }
3167 for (auto & mode : mModes) {
3168 auto & itMode = mode.second;
3169 if ( strcmp (itMode.name, name) ==0 ) {
3170 *drmMode = itMode;
3171 ret = 0;
3172 break;
3173 }
3174 }
3175 return ret;
3176}
3177
3178int32_t ModePolicy::groupDisplayModes()
3179{
3180 /* no need to regenerate groupId if without QMS/VRR support */
3181 if ( mDisplayType != DISPLAY_TYPE_TV) {
3182 if (!(supportVrr()) || !mSeamlessSwitchEnabled) {
3183 return 0;
3184 }
3185 }
3186 /* clear the old group modes */
3187 mMesonGroupModes.clear();
3188
3189 for (auto & mode : mModes) {
3190 auto & itMode = mode.second;
3191 bool needRegroup = true;
3192 for (auto & groupModes : mMesonGroupModes) {
3193 int groupId = groupModes.first;
3194 auto& itGroupModes = groupModes.second;
3195
3196 // do not check interlace mode,
3197 // interlace mode does not support vrr
3198 if (strstr(itMode.name, "i") != NULL)
3199 break;
3200
3201 // only support resolution >= 720P
3202 if (itMode.pixelW < 1280 || itMode.pixelH < 720)
3203 break;
3204
3205 if (!itGroupModes.empty()) {
3206 /* only need check the first item*/
3207 drm_mode_info_t *gmodePtr = itGroupModes[0];
3208 if (gmodePtr->pixelW == itMode.pixelW && gmodePtr->pixelH == itMode.pixelH
3209 && isSeamlessMode(itMode, *gmodePtr)) {
3210 itMode.groupId = groupId;
3211 itGroupModes.push_back(&itMode);
3212 needRegroup = false;
3213 break;
3214 }
3215 }
3216 }
3217
3218 if (needRegroup) {
3219 itMode.groupId = mMesonGroupModes.size();
3220 auto iter = mMesonGroupModes.emplace(mMesonGroupModes.size(),
3221 std::vector<drm_mode_info_t *> ());
3222 auto & modesWithSameGroup = iter.first->second;
3223 modesWithSameGroup.push_back(&itMode);
3224 }
3225 }
3226
3227 return 0;
3228}
3229
3230void ModePolicy::updateDrmfd(int drmFd)
3231{
3232 MESON_LOGD("updateDrmfd:%d\n", drmFd);
3233 if (drmFd >= 0)
3234 mDrmFd = drmFd;
3235}
3236
3237void ModePolicy::seamlessSwitchEnabled(bool enable)
3238{
3239 MESON_LOGD("seamlessSwitchEnabled:%d\n", enable);
3240 mSeamlessSwitchEnabled = enable;
3241}
3242
3243void ModePolicy::setQMSVRR(char* curDisplayMode, char* final_displaymode )
3244{
3245 if (!curDisplayMode || !final_displaymode) {
3246 MESON_LOGE("\n %s %d invalid parameter\n", __FUNCTION__,__LINE__);
3247 return;
3248 }
3249 drm_mode_info_t curDrmMode;
3250 drm_mode_info_t finalDrmMode;
3251 bool isSeamless = false;
3252 getDrmModeInfoFromName(curDisplayMode, &curDrmMode);
3253 getDrmModeInfoFromName(final_displaymode, &finalDrmMode);
3254 isSeamless = (curDrmMode.groupId == finalDrmMode.groupId);
3255 MESON_LOGD("\n %s %d curDisplayMode:%s, final_displaymode:%s isSeamless:%d\n",
3256 __FUNCTION__,__LINE__, curDisplayMode, final_displaymode, isSeamless);
3257 int enableVrr = 0;
3258 int updateBrr = isSeamless ? 0 : 1;
3259 char sEnableVrr[3] = {'\0'};
3260 char sUpdateBrr[3] = {'\0'};
3261 if (supportVrr()) {
3262 bool modeIsVrrMode = true;
3263 if (updateBrr) {
3264 modeIsVrrMode = isVrrGroupedMode(finalDrmMode);
3265 }
3266 enableVrr = (mSeamlessSwitchEnabled && modeIsVrrMode) ? 1 : 0;
3267 sprintf(sUpdateBrr, "%d",updateBrr);
3268 MESON_LOGD("\n %s %d mSeamlessSwitchEnabled:%d, modeIsVrrMode:%d enableVrr:%d, updateBrr:%d\n",
3269 __FUNCTION__,__LINE__, mSeamlessSwitchEnabled, modeIsVrrMode, enableVrr, updateBrr);
3270 setDisplayAttribute(DISPLAY_BRR_UPDATE, sUpdateBrr);
3271 }
3272 sprintf(sEnableVrr, "%d",enableVrr);
3273 setDisplayAttribute(DISPLAY_VRR_ENABLED, sEnableVrr);
3274
3275}
leng.fang91856072024-06-07 14:12:54 +08003276int32_t bindCrtcAndConnector(drmModeCrtc *crtc, drmModeConnector *conn)
3277{
3278 int ret = -1;
3279 MESON_LOGI("bindCrtcAndConnector:%p, %p\n", crtc, conn);
3280 if (g_Policy.get()) {
3281 ret = g_Policy->bindConnector(conn);
3282 ret |= g_Policy->bindCrtc(crtc);
3283 }
3284 return ret;
3285}
3286
3287void initModePolicyFun(drmModeCrtc *crtc, drmModeConnector *conn, CompositorFunctionCallBack callback)
3288{
3289 if (!g_Adapter.get())
3290 g_Adapter = std::make_shared<DisplayAdapter>(crtc, conn);
3291
3292 if (!g_Policy.get())
3293 g_Policy = std::make_shared<ModePolicy>(g_Adapter, 0);
3294
3295 if (g_Policy.get() && g_Adapter.get()) {
3296 g_Adapter->registerCallBack(callback);
3297 bindCrtcAndConnector(crtc, conn);
3298 }
3299}
3300
3301void initModePolicy(drmModeCrtc *crtc, drmModeConnector *conn, CompositorFunctionCallBack callback)
3302{
3303 //initModePolicyFun(crtc, conn,callback);
3304 if (g_Policy.get()) {
3305 g_Policy->initialize();
3306 }
3307}
3308
3309void onHotplug(bool connected)
3310{
3311 if (g_Policy.get())
3312 g_Policy->onHotplug(connected);
3313}
3314
3315void getPreferredBootConfig(char *name)
3316{
3317 std::string mode;
3318 if (g_Policy.get()) {
3319 if (g_Policy->getPreferredBootConfig(mode) == 0)
3320 strcpy(name, mode.c_str());
3321 }
3322}
3323
3324void setHdrConversionPolicy(bool passthrough, int32_t forceType)
3325{
3326 if (g_Policy.get())
3327 g_Policy->setHdrConversionPolicy(passthrough, forceType);
3328}
3329
3330void setDvMode(int amdv_mode)
3331{
3332 std::string mode = to_string(amdv_mode);
3333 if (g_Policy.get())
3334 g_Policy->setDvMode(mode);
3335}
3336
3337void setColorSpace(char *colorspace)
3338{
3339 std::string color = colorspace;
3340 if (g_Policy.get())
3341 g_Policy->setColorSpace(color);
3342}
3343
3344void setBootConfig(char *mode, bool auto_mode)
3345{
3346 std::string config = mode;
3347 if (g_Policy.get()) {
3348 if (auto_mode)
3349 g_Policy->clearBootConfig();
3350 else
3351 g_Policy->setBootConfig(config);
3352 }
3353}
3354
3355bool setActiveConfig(char *mode)
3356{
3357 std::string config = mode;
3358 if (g_Policy.get()) {
3359 g_Policy->setActiveConfig(config);
3360 return true;
3361 }
3362 return false;
3363}
3364
3365bool setPolicyByAppName(const char *name, int state)
3366{
limin.tiana0140a72024-10-12 07:28:49 +00003367 MESON_LOGD("\n %s %d name:%s state:%d \n", __FUNCTION__,__LINE__,name,state);
leng.fang91856072024-06-07 14:12:54 +08003368 if (g_Policy.get()) {
3369 if (state == 1 && !strcmp(name, "netflix")) {
limin.tiana0140a72024-10-12 07:28:49 +00003370 g_Policy->setPolicy(MESON_POLICY_FRAMERATE);
leng.fang91856072024-06-07 14:12:54 +08003371 } else {
3372 g_Policy->setPolicy(MESON_POLICY_MIX);
3373 }
3374 return true;
3375 }
3376 return false;
3377}
3378
3379bool updateEnv()
3380{
3381 if (g_Policy.get())
3382 return g_Policy->updateEnv();
3383 return false;
3384}
3385
3386bool getModeNameForPix(char *name,
3387 int32_t width, int32_t height, uint32_t refresh, uint32_t flags)
3388{
3389 if (g_Policy.get())
3390 return g_Policy->getModeNameForPix(name, width, height, refresh / 1000, flags);
3391 return false;
3392}
limin.tiana9a091a2024-09-23 07:54:32 +00003393void updateDrmfd(int fd)
3394{
3395 MESON_LOGD("\n %s %d fd:%d, g_Policy.get():%p\n",__FUNCTION__,__LINE__,fd, g_Policy.get());
3396 if (g_Policy.get())
3397 g_Policy->updateDrmfd(fd);
3398}
3399void seamlessSwitchEnabled(bool enable)
3400{
3401 if (g_Policy.get())
3402 g_Policy->seamlessSwitchEnabled(enable);
3403}
3404
leng.fangc78bdb62024-10-21 16:36:41 +08003405int setPriority(int priority)
3406{
3407 if (g_Policy.get())
3408 return g_Policy->setHdrPriority(priority);
3409 return -1;
3410}
3411
3412int getPriority()
3413{
3414 if (g_Policy.get())
3415 return g_Policy->getHdrPriority();
3416 return 0;
3417}