| /* |
| * Copyright (c) 2022 Amlogic, Inc. All rights reserved. |
| * |
| * This source code is subject to the terms and conditions defined in the |
| * file 'LICENSE' which is part of this source code package. |
| * |
| * Description: |
| */ |
| |
| #include "ModePolicy.h" |
| #include <modepolicy/mode_ubootenv.h> |
| #include <inttypes.h> |
| #include <sys/utsname.h> |
| #include <memory> |
| #include <sys/ioctl.h> |
| |
| //#include <systemcontrol.h> |
| static int g_activeLevel= 3; |
| |
| /* testing if tv support this displaymode and deepcolor combination, then if cat result is 1: support, 0: not */ |
| #define DISPLAY_HDMI_VALID_MODE "/sys/class/amhdmitx/amhdmitx0/valid_mode" |
| |
| #define PROP_DEFAULT_COLOR "ro_vendor_platform_default_color" |
| #define LOW_POWER_DEFAULT_COLOR "ro_vendor_low_power_default_color" /* Set default deep color is 8bit for Low Power Mode */ |
| #define UBOOTENV_COLORATTRIBUTE "ubootenv.var.colorattribute" |
| |
| #define EDID_MAX_SIZE 2049 |
| #define MODE_8K4K_PREFIX "4320p" |
| #define PROP_VALUE_MAX 92 |
| |
| #define HDMI_HDR_STATUS_HDR10PLUS 0 |
| #define HDMI_HDR_STATUS_DolbyVision_STD 1 |
| #define HDMI_HDR_STATUS_DolbyVision_Lowlatency 2 |
| #define HDMI_HDR_STATUS_HDR10_ST2084 3 |
| #define HDMI_HDR_STATUS_HDR10_TRADITIONAL 4 |
| #define HDMI_HDR_STATUS_HDR_HLG 5 |
| #define HDMI_HDR_STATUS_SDR 6 |
| |
| enum { |
| DISPLAY_TYPE_NONE = 0, |
| DISPLAY_TYPE_TABLET = 1, |
| DISPLAY_TYPE_MBOX = 2, |
| DISPLAY_TYPE_TV = 3, |
| DISPLAY_TYPE_REPEATER = 4 |
| }; |
| |
| static const char* AMDV_MODE_TYPE[] = { |
| "DV_RGB_444_8BIT", |
| "DV_YCbCr_422_12BIT", |
| "LL_YCbCr_422_12BIT", |
| "LL_RGB_444_10BIT", |
| "LL_RGB_444_12BIT" |
| }; |
| |
| static const char* ALLM_MODE_CAP[] = { |
| "0", |
| "1", |
| }; |
| |
| static const char* ALLM_MODE[] = { |
| "-1", |
| "0", |
| "1", |
| }; |
| |
| static const char* CONTENT_TYPE_CAP[] = { |
| "graphics", |
| "photo", |
| "cinema", |
| "game", |
| }; |
| |
| /*****************************************/ |
| /* deepcolor */ |
| |
| //this is check hdmi mode(4K60/4k50) list |
| static const char* COLOR_ATTRIBUTE_LIST[] = { |
| COLOR_RGB_8BIT, |
| COLOR_YCBCR444_8BIT, |
| COLOR_YCBCR420_8BIT, |
| COLOR_YCBCR422_8BIT, |
| }; |
| |
| //this is check hdmi mode list |
| static const char* COLOR_ATTRIBUTE_LIST_8BIT[] = { |
| COLOR_RGB_8BIT, |
| COLOR_YCBCR444_8BIT, |
| COLOR_YCBCR422_8BIT, |
| }; |
| |
| std::shared_ptr<ModePolicy> g_Policy; |
| std::shared_ptr<DisplayAdapter> g_Adapter; |
| |
| ModePolicy::ModePolicy() { |
| mDisplayType = DISPLAY_TYPE_MBOX; |
| mPolicy = MESON_POLICY_MIX; |
| mReason = OUTPUT_CHANGE_BY_INIT; |
| mDisplayId = 0; |
| memset(&mConnectorType, 0, sizeof(mConnectorType)); |
| memset(&mModeConType, 0, sizeof(mModeConType)); |
| memset(&mConData, 0, sizeof(mConData)); |
| memset(&mSceneOutInfo, 0, sizeof(mSceneOutInfo)); |
| memset(&mState, 0, sizeof(mState)); |
| memset(&mDvInfo, 0, sizeof(mDvInfo)); |
| mDisplayWidth = 0; |
| mDisplayHeight = 0; |
| mFracMode = MODE_FRACTION; |
| mEnvLock = PTHREAD_MUTEX_INITIALIZER; |
| mSeamlessSwitchEnabled = true; |
| } |
| |
| ModePolicy::ModePolicy(std::shared_ptr<DisplayAdapter> adapter, const uint32_t displayId) { |
| mAdapter = adapter; |
| mDisplayType = DISPLAY_TYPE_MBOX; |
| mPolicy = MESON_POLICY_MIX; |
| mReason = OUTPUT_CHANGE_BY_INIT; |
| mDisplayId = displayId; |
| memset(&mConnectorType, 0, sizeof(mConnectorType)); |
| memset(&mModeConType, 0, sizeof(mModeConType)); |
| memset(&mConData, 0, sizeof(mConData)); |
| memset(&mSceneOutInfo, 0, sizeof(mSceneOutInfo)); |
| memset(&mState, 0, sizeof(mState)); |
| memset(&mDvInfo, 0, sizeof(mDvInfo)); |
| mDisplayWidth = 0; |
| mDisplayHeight = 0; |
| mFracMode = MODE_FRACTION; |
| mEnvLock = PTHREAD_MUTEX_INITIALIZER; |
| mSeamlessSwitchEnabled = true; |
| } |
| |
| ModePolicy::~ModePolicy() { |
| |
| } |
| |
| bool ModePolicy::getBootEnv(const char *key, char *value) { |
| const char* p_value; |
| const char* envName = key; |
| if (strstr(key, PROFIX_UBOOTENV_VAR) != NULL) |
| envName = key + strlen(PROFIX_UBOOTENV_VAR); |
| p_value = bootenv_get(envName); |
| MESON_LOGD("get key:%s value:%s", key, p_value ? p_value : "novalue"); |
| |
| if (p_value) { |
| strcpy(value, p_value); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| int ModePolicy::getBootenvInt(const char* key, int defaultVal) { |
| int value = defaultVal; |
| const char* p_value; |
| const char* envName = key; |
| if (strstr(key, PROFIX_UBOOTENV_VAR) != NULL) |
| envName = key + strlen(PROFIX_UBOOTENV_VAR); |
| p_value = bootenv_get(envName); |
| if (p_value) { |
| value = atoi(p_value); |
| } |
| return value; |
| } |
| |
| void ModePolicy::setBootEnv(const char* key, const char* value) { |
| const char* p_value; |
| const char* envName = key; |
| if (strstr(key, PROFIX_UBOOTENV_VAR) != NULL) |
| envName = key + strlen(PROFIX_UBOOTENV_VAR); |
| p_value = bootenv_get(envName); |
| |
| if (p_value && !strcmp(p_value, value)) { |
| MESON_LOGV("value is equal, do not set"); |
| return; |
| } |
| |
| MESON_LOGD("set key:%s value:%s", key, value); |
| bootenv_update(envName, value); |
| } |
| |
| |
| // TODO: need refactor |
| #ifdef HDR_AMDV_PROPERTY |
| void ModePolicy::getDvCap(struct meson_hdr_info *data) { |
| if (!data) { |
| MESON_LOGE("%s data is NULL\n", __FUNCTION__); |
| return; |
| } |
| |
| std::string amdv_cap; |
| int cap = 0; |
| getDisplayAttribute(DISPLAY_AMDV_CAP, amdv_cap); |
| strcpy(data->dv_cap, amdv_cap.c_str()); |
| cap = atoi(data->dv_cap); |
| |
| if (cap != 0) { |
| uint32_t index = (cap & (1 << 2)) ? 19 : 17; |
| if ((strlen(data->dv_max_mode) + strlen(DISPLAY_MODE_LIST[index]) + 1) < sizeof(data->dv_max_mode)) { |
| strcat(data->dv_max_mode, DISPLAY_MODE_LIST[index]); |
| strcat(data->dv_max_mode, ","); |
| } else { |
| MESON_LOGE("DisplayMode strcat overflow: src=%s, dst=%s\n", DISPLAY_MODE_LIST[index], data->dv_max_mode); |
| } |
| |
| index = ((cap & 0xf8) >> 3); |
| for (int i = 0; i < ARRAY_SIZE(AMDV_MODE_TYPE); i++) { |
| if (index & (1 << i)) { |
| strcat(data->dv_deepcolor, AMDV_MODE_TYPE[i]); |
| strcat(data->dv_deepcolor, ","); |
| } |
| } |
| } |
| } |
| #else |
| void ModePolicy::getDvCap(struct meson_hdr_info *data) { |
| if (!data) { |
| MESON_LOGE("%s data is NULL\n", __FUNCTION__); |
| return; |
| } |
| |
| std::string amdv_cap; |
| getDisplayAttribute(DISPLAY_AMDV_CAP2, amdv_cap); |
| strcpy(data->dv_cap, amdv_cap.c_str()); |
| |
| if (strstr(data->dv_cap, "DolbyVision RX support list") != NULL) { |
| memset(data->dv_max_mode, 0, sizeof(data->dv_max_mode)); |
| memset(data->dv_deepcolor, 0, sizeof(data->dv_deepcolor)); |
| for (int i = ARRAY_SIZE(DISPLAY_MODE_LIST) - 1; i >= 0; i--) { |
| if (strstr(data->dv_cap, DISPLAY_MODE_LIST[i]) != NULL) { |
| if ((strlen(data->dv_max_mode) + strlen(DISPLAY_MODE_LIST[i]) + 1) < sizeof(data->dv_max_mode)) { |
| strcpy(data->dv_max_mode, DISPLAY_MODE_LIST[i]); |
| } else { |
| MESON_LOGE("DisplayMode strcat overflow: src=%s, dst=%s\n", DISPLAY_MODE_LIST[i], data->dv_max_mode); |
| } |
| break; |
| } |
| } |
| |
| for (int i = 0; i < sizeof(AMDV_MODE_TYPE)/sizeof(AMDV_MODE_TYPE[0]); i++) { |
| if (strstr(data->dv_cap, AMDV_MODE_TYPE[i])) { |
| if ((strlen(data->dv_deepcolor) + strlen(AMDV_MODE_TYPE[i]) + 2) < sizeof(data->dv_deepcolor)) { |
| strcat(data->dv_deepcolor, AMDV_MODE_TYPE[i]); |
| strcat(data->dv_deepcolor, ","); |
| } else { |
| MESON_LOGE("DisplayMode strcat overflow: src=%s, dst=%s\n", AMDV_MODE_TYPE[i], data->dv_deepcolor); |
| break; |
| } |
| } |
| } |
| MESON_LOGI("TV dv info: mode:%s deepcolor: %s\n", data->dv_max_mode, data->dv_deepcolor); |
| } else { |
| MESON_LOGE("TV isn't support dv: %s\n", data->dv_cap); |
| } |
| } |
| #endif |
| |
| void ModePolicy::getHdmiDcCap(char* dc_cap, int32_t len) { |
| if (!dc_cap) { |
| MESON_LOGE("%s dc_cap is NULL\n", __FUNCTION__); |
| return; |
| } |
| |
| int count = 0; |
| while (true) { |
| sysfs_get_string_original(DISPLAY_HDMI_DEEP_COLOR, dc_cap, len); |
| if (strlen(dc_cap) > 0) |
| break; |
| |
| if (count >= 5) { |
| MESON_LOGE("read dc_cap fail\n"); |
| break; |
| } |
| count++; |
| usleep(500000); |
| } |
| } |
| |
| int ModePolicy::getHdmiSinkType() { |
| char sinkType[MESON_MODE_LEN] = {0}; |
| if (sysfs_get_string(DISPLAY_HDMI_SINK_TYPE, sinkType, MESON_MODE_LEN) != 0) |
| return HDMI_SINK_TYPE_NONE; |
| |
| if (NULL != strstr(sinkType, "sink")) { |
| return HDMI_SINK_TYPE_SINK; |
| } else if (NULL != strstr(sinkType, "repeater")) { |
| return HDMI_SINK_TYPE_REPEATER; |
| } else { |
| return HDMI_SINK_TYPE_NONE; |
| } |
| } |
| |
| void ModePolicy::getHdmiEdidStatus(char* edidstatus, int32_t len) { |
| if (!edidstatus) { |
| MESON_LOGE("%s edidstatus is NULL\n", __FUNCTION__); |
| return; |
| } |
| |
| sysfs_get_string(DISPLAY_EDID_STATUS, edidstatus, len); |
| } |
| |
| int32_t ModePolicy::setHdrStrategy(int32_t policy, const char *type) { |
| SYS_LOGI("%s type:%s policy:%s", __func__, |
| meson_hdrPolicyToString(policy), type); |
| |
| //1. update env policy |
| std::string value = std::to_string(policy); |
| setBootEnv(UBOOTENV_HDR_POLICY, value.c_str()); |
| |
| if (policy == MESON_HDR_POLICY_SOURCE) { |
| if (isDVEnable()) { |
| setBootEnv(UBOOTENV_DOLBYSTATUS, "0"); |
| } |
| } else { |
| char dvstatus[MESON_MODE_LEN] = {0}; |
| if (isDVEnable()) { |
| sprintf(dvstatus, "%d", mSceneOutInfo.amdv_type); |
| setBootEnv(UBOOTENV_DOLBYSTATUS, dvstatus); |
| } |
| } |
| |
| int32_t priority = MESON_HDR10_PRIORITY; |
| value = std::to_string(MESON_HDR10_PRIORITY); |
| if (strstr(type, AMDV_DISABLE_FORCE_SDR)) { |
| priority = MESON_SDR_PRIORITY; |
| value = std::to_string(MESON_SDR_PRIORITY); |
| } |
| |
| //2. set current hdmi mode |
| meson_mode_set_policy_input(mModeConType, &mConData); |
| getDisplayMode(mCurrentMode); |
| |
| if (!meson_mode_support_mode(mModeConType, priority, mCurrentMode)) { |
| setBootEnv(UBOOTENV_HDR_FORCE_MODE, type); |
| setSourceOutputMode(mCurrentMode); |
| } else { |
| MESON_LOGD("%s mode check failed", __func__); |
| return -EINVAL; |
| } |
| |
| return 0; |
| } |
| |
| void ModePolicy::getHdrStrategy(char* value) { |
| char hdr_policy[MESON_MODE_LEN] = {0}; |
| |
| memset(hdr_policy, 0, MESON_MODE_LEN); |
| getBootEnv(UBOOTENV_HDR_POLICY, hdr_policy); |
| |
| if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) { |
| strcpy(value, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]); |
| } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) { |
| strcpy(value, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]); |
| } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE])) { |
| strcpy(value, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]); |
| } else if (strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) { |
| strcpy(value, AMDV_POLICY_FORCE_MODE); |
| } |
| MESON_LOGI("get uboot HdrStrategy is [%s]", value); |
| } |
| |
| int32_t ModePolicy::setHdrPriority(int32_t type) { |
| MESON_LOGI("setHdrPriority is [%s] getHdrPriority is [%s]\n", meson_hdrPriorityToString(type), |
| meson_hdrPriorityToString(getHdrPriority())); |
| |
| if (getHdrPriority() != type) { |
| getConnectorData(&mConData, &mDvInfo); |
| meson_mode_set_policy_input(mModeConType, &mConData); |
| getDisplayMode(mCurrentMode); |
| |
| if (!meson_mode_support_mode(mModeConType, type, mCurrentMode)) { |
| std::string value = std::to_string(type); |
| |
| setBootEnv(UBOOTENV_HDR_PRIORITY, value.c_str()); |
| setSourceOutputMode(mCurrentMode); |
| } else { |
| MESON_LOGD("%s mode check failed", __func__); |
| return -EINVAL; |
| } |
| } else { |
| MESON_LOGI("setHdrPriority is [%d] and getHdrPriority [%d],They are equals", type, getHdrPriority()); |
| } |
| |
| return 0; |
| } |
| |
| int32_t ModePolicy::getHdrPriority() { |
| char hdr_priority[MESON_MODE_LEN] = {0}; |
| meson_hdr_priority_e value = MESON_DOLBY_VISION_PRIORITY; |
| bool dv_support = isMboxSupportDV(); |
| bool hdr_support = isTvSupportHDR(); |
| meson_hdr_priority_e act_hdr_priority = dv_support ? |
| MESON_DOLBY_VISION_PRIORITY : |
| (hdr_support ? MESON_HDR10_PRIORITY : MESON_SDR_PRIORITY); |
| |
| memset(hdr_priority, 0, MESON_MODE_LEN); |
| getBootEnv(UBOOTENV_HDR_PRIORITY, hdr_priority); |
| |
| if (strlen(hdr_priority) == 0) { |
| return act_hdr_priority; |
| } |
| |
| value = (meson_hdr_priority_e)atoi(hdr_priority); |
| |
| if (value <= MESON_SDR_PRIORITY) { |
| if (!dv_support && value == MESON_DOLBY_VISION_PRIORITY) |
| value = MESON_HDR10_PRIORITY; |
| if (!hdr_support && value == MESON_HDR10_PRIORITY) |
| value = MESON_SDR_PRIORITY; |
| value = (act_hdr_priority > value ? act_hdr_priority : value); |
| } else if (value >= MESON_G_DV_HDR10_HLG) { |
| switch (value) { |
| case MESON_G_DV_HDR10_HLG: |
| value = dv_support ? value : (hdr_support ? MESON_G_HDR10_HLG : MESON_G_SDR); |
| break; |
| case MESON_G_DV_HDR10: |
| value = dv_support ? value : (hdr_support ? MESON_G_HDR10 : MESON_G_SDR); |
| break; |
| case MESON_G_DV_HLG: |
| value = dv_support ? value : (hdr_support ? MESON_G_HLG : MESON_G_SDR); |
| break; |
| case MESON_G_DV: |
| value = dv_support ? value : MESON_G_SDR; |
| break; |
| case MESON_G_HDR10_HLG: |
| case MESON_G_HDR10: |
| case MESON_G_HLG: |
| value = hdr_support ? value : MESON_G_SDR; |
| break; |
| default: |
| break; |
| } |
| } |
| if ((value >= MESON_DOLBY_VISION_PRIORITY && value <= MESON_SDR_PRIORITY) |
| || (value >= MESON_G_DV_HDR10_HLG && value <= MESON_G_SDR)) { |
| MESON_LOGI("%s is [%s]", __FUNCTION__, meson_hdrPriorityToString(value)); |
| } else { |
| MESON_LOGE("%s [%d] is invalid", __FUNCTION__, value); |
| } |
| |
| MESON_LOGI("get uboot HdrPriority is [%s]", meson_hdrPriorityToString(value)); |
| return (int32_t)value; |
| } |
| |
| int32_t ModePolicy::getCurrentHdrPriority(void) { |
| meson_hdr_priority_e value = MESON_DOLBY_VISION_PRIORITY; |
| |
| std::string cur_hdr_priority; |
| getDisplayAttribute(DISPLAY_HDR_PRIORITY, cur_hdr_priority); |
| |
| value = (meson_hdr_priority_e)atoi(cur_hdr_priority.c_str()); |
| if ((value >= MESON_DOLBY_VISION_PRIORITY && value <= MESON_SDR_PRIORITY) |
| || (value >= MESON_G_DV_HDR10_HLG && value <= MESON_G_SDR)) { |
| MESON_LOGI("%s is [%s]", __FUNCTION__, meson_hdrPriorityToString(value)); |
| } else { |
| MESON_LOGE("%s [%d] is invalid", __FUNCTION__, value); |
| } |
| |
| return (int32_t)value; |
| } |
| |
| void ModePolicy::gethdrforcemode(char* value) { |
| if (!value) { |
| MESON_LOGE("%s value is NULL\n", __FUNCTION__); |
| return; |
| } |
| |
| bool ret = false; |
| char hdr_force_mode[MESON_MODE_LEN] = {0}; |
| |
| memset(hdr_force_mode, 0, MESON_MODE_LEN); |
| ret = getBootEnv(UBOOTENV_HDR_FORCE_MODE, hdr_force_mode); |
| if (ret) { |
| strcpy(value, hdr_force_mode); |
| } else { |
| strcpy(value, FORCE_AMDV); |
| } |
| |
| MESON_LOGI("get hdr force mode is [%s]", value); |
| } |
| |
| bool ModePolicy::isTvDVEnable() { |
| bool ret = false; |
| char amdv_enable[MESON_MODE_LEN]; |
| ret = getBootEnv(UBOOTENV_DV_ENABLE, amdv_enable); |
| if (!ret) { |
| if (isMboxSupportDV()) { |
| strcpy(amdv_enable, "1"); |
| } else { |
| strcpy(amdv_enable, "0"); |
| } |
| } |
| MESON_LOGI("dv_enable:%s\n", amdv_enable); |
| |
| if (!strcmp(amdv_enable, "0")) { |
| return false; |
| } else { |
| return true; |
| } |
| } |
| |
| bool ModePolicy::isDVEnable() { |
| if (isMboxSupportDV()) { |
| if (!strcmp(mDvInfo.amdv_enable, "0") ) { |
| return false; |
| } else { |
| return true; |
| } |
| } else { |
| return false; |
| } |
| } |
| |
| /* * |
| * @Description: Detect Whether TV support dv |
| * @return: if TV support return true, or false |
| * if true, mode is the Highest resolution Tv dv supported |
| * else mode is "" |
| */ |
| bool ModePolicy::isTvSupportDV() { |
| if (DISPLAY_TYPE_TV == mDisplayType) { |
| MESON_LOGI("Current Device is TV, no dv_cap\n"); |
| return false; |
| } |
| |
| if (strstr(mConData.hdr_info.dv_cap, "DolbyVision RX support list") == NULL) { |
| if (atoi(mConData.hdr_info.dv_cap) == 0) |
| return false; |
| } |
| |
| return true; |
| } |
| |
| #ifdef HDR_AMDV_PROPERTY |
| void ModePolicy::parseHdmiHdrCapabilities(drm_hdr_capabilities & hdrCaps) |
| { |
| std::string hdr_cap; |
| int cap = 0; |
| getDisplayAttribute(DISPLAY_HDR_CAP, hdr_cap); |
| MESON_LOGV("parseHdmiHdrCapabilities: hdr cap: %s", hdr_cap.c_str()); |
| memset(&hdrCaps, 0, sizeof(drm_hdr_capabilities)); |
| cap = atoi(hdr_cap.c_str()); |
| |
| if (cap & 0x01) |
| hdrCaps.HDR10PlusSupported = true; |
| |
| if (cap & (1 << 3)) |
| hdrCaps.HDR10Supported = true; |
| |
| if (cap & (1 << 4)) |
| hdrCaps.HLGSupported = true; |
| } |
| |
| void ModePolicy::parseDvCapabilities() |
| { |
| std::string amdv_cap; |
| int cap = 0; |
| getDisplayAttribute(DISPLAY_AMDV_CAP, amdv_cap); |
| MESON_LOGV("parseDvCapabilities: dv cap: %s", amdv_cap.c_str()); |
| cap = atoi(amdv_cap.c_str()); |
| if (cap != 0 && getDvSupportStatus()) { |
| mHdrCapabilities.DVSupported = true; |
| if ((cap & (1 << 2)) == 0) |
| mHdrCapabilities.AMDV_4K30_Supported = true; |
| } |
| } |
| #else |
| int32_t getLineValue(const char *lineStr, const char *magicStr) { |
| int len = 0; |
| char value[100] = {0}; |
| const char *pos = NULL; |
| |
| if ((NULL == lineStr) || (NULL == magicStr)) { |
| MESON_LOGE("line string: %s, magic string: %s\n", lineStr, magicStr); |
| return 0; |
| } |
| |
| if (NULL != (pos = strstr(lineStr, magicStr))) { |
| pos = pos + strlen(magicStr); |
| const char* start = pos; |
| while ((*start <= '9' && *start >= '0') && (strlen(start) > 0)) |
| start++; |
| |
| len = start - pos; |
| strncpy(value, pos, len); |
| value[len] = '\0'; |
| return atoi(value); |
| } |
| |
| return 0; |
| } |
| |
| void ModePolicy::parseHdmiHdrCapabilities(drm_hdr_capabilities & hdrCaps) |
| { |
| std::string hdr_cap; |
| char buf[1024 + 1] = { 0 }; |
| char* pos = buf; |
| |
| getDisplayAttribute(DISPLAY_HDR_CAP2, hdr_cap); |
| MESON_LOGV("parseHdmiHdrCapabilities: hdr cap: %s", hdr_cap.c_str()); |
| |
| strcpy(buf, hdr_cap.c_str()); |
| memset(&hdrCaps, 0, sizeof(drm_hdr_capabilities)); |
| |
| if (pos != NULL) pos = strstr(pos, "HDR10Plus Supported: "); |
| if ((NULL != pos) && ('1' == *(pos + strlen("HDR10Plus Supported: ")))) { |
| hdrCaps.HDR10PlusSupported = true; |
| } |
| |
| if (pos != NULL) pos = strstr(pos, "SMPTE ST 2084: "); |
| if ((NULL != pos) && ('1' == *(pos + strlen("SMPTE ST 2084: ")))) { |
| hdrCaps.HDR10Supported = true; |
| |
| hdrCaps.maxLuminance = getLineValue(pos, "Max: "); |
| hdrCaps.avgLuminance = getLineValue(pos, "Avg: "); |
| hdrCaps.minLuminance = getLineValue(pos, "Min: "); |
| } |
| |
| if (pos != NULL) { |
| char* hybrif = strstr(pos, "Hybrif Log-Gamma: "); |
| if (NULL != hybrif) { |
| if ('1' == *(hybrif + strlen("Hybrif Log-Gamma: "))) |
| hdrCaps.HLGSupported = true; |
| } else { |
| /* kernel 5.4, content change to: Hybrid Log-Gamma */ |
| char* hybrid = strstr(pos, "Hybrid Log-Gamma: "); |
| if ((NULL != hybrid) && ('1' == *(hybrid + strlen("Hybrid Log-Gamma: ")))) |
| hdrCaps.HLGSupported = true; |
| } |
| } |
| } |
| |
| void ModePolicy::parseDvCapabilities() |
| { |
| std::string amdv_cap; |
| char buf[1024 + 1] = { 0 }; |
| |
| getDisplayAttribute(DISPLAY_AMDV_CAP2, amdv_cap); |
| MESON_LOGV("parseDvCapabilities: dv cap: %s", amdv_cap.c_str()); |
| |
| strcpy(buf, amdv_cap.c_str()); |
| if (((NULL != strstr(buf, "2160p30hz")) || (NULL != strstr(buf, "2160p60hz"))) && |
| getDvSupportStatus()) { |
| mHdrCapabilities.DVSupported = true; |
| if (strstr(buf, "2160p30hz")) |
| mHdrCapabilities.AMDV_4K30_Supported = true; |
| } else { |
| mHdrCapabilities.DVSupported = false; |
| } |
| } |
| #endif |
| |
| void ModePolicy::updateHdrCaps() { |
| uint32_t type = mConnector ? mConnector->connector_type : 0; |
| bool supportDv = getDvSupportStatus(); |
| |
| memset(&mHdrCapabilities, 0, sizeof(drm_hdr_capabilities)); |
| if (type == DRM_MODE_CONNECTOR_HDMIA) { |
| parseHdmiHdrCapabilities(mHdrCapabilities); |
| parseDvCapabilities(); |
| } |
| /* for TV product*/ |
| if (type == DRM_MODE_CONNECTOR_MESON_LVDS_A || type == DRM_MODE_CONNECTOR_MESON_LVDS_B || |
| type == DRM_MODE_CONNECTOR_MESON_LVDS_C || type == DRM_MODE_CONNECTOR_MESON_VBYONE_A || |
| type == DRM_MODE_CONNECTOR_MESON_VBYONE_B || type == DRM_MODE_CONNECTOR_LVDS) { |
| constexpr int sDefaultMinLumiance = 0; |
| constexpr int sDefaultMaxLumiance = 500; |
| |
| mHdrCapabilities.DVSupported = supportDv; |
| mHdrCapabilities.HLGSupported = true; |
| mHdrCapabilities.HDR10Supported = true; |
| mHdrCapabilities.maxLuminance = sDefaultMaxLumiance; |
| mHdrCapabilities.avgLuminance = sDefaultMaxLumiance; |
| mHdrCapabilities.minLuminance = sDefaultMinLumiance; |
| parseDvCapabilities(); |
| MESON_LOGD("dv:%d, hlg:%d, hdr10:%d, hdr10+:%d max:%d, avg:%d, min:%d\n", |
| mHdrCapabilities.DVSupported ? 1 : 0, |
| mHdrCapabilities.HLGSupported ? 1 : 0, |
| mHdrCapabilities.HDR10Supported ? 1 : 0, |
| mHdrCapabilities.HDR10PlusSupported ? 1 : 0, |
| mHdrCapabilities.maxLuminance, |
| mHdrCapabilities.avgLuminance, |
| mHdrCapabilities.minLuminance); |
| } |
| } |
| |
| |
| void ModePolicy::getHdrCapabilities(drm_hdr_capabilities * caps) |
| { |
| if (!caps) |
| return; |
| |
| *caps = mHdrCapabilities; |
| } |
| |
| bool ModePolicy::isTvSupportHDR() { |
| if (DISPLAY_TYPE_TV == mDisplayType) { |
| MESON_LOGI("Current Device is TV, no hdr_cap\n"); |
| return false; |
| } |
| |
| drm_hdr_capabilities hdrCaps; |
| getHdrCapabilities(&hdrCaps); |
| |
| if (hdrCaps.HLGSupported || |
| hdrCaps.HDR10Supported || |
| hdrCaps.HDR10PlusSupported) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| bool ModePolicy::isHdrResolutionPriority() { |
| return sys_get_bool_prop(PROP_HDR_RESOLUTION_PRIORITY, true); |
| } |
| |
| bool ModePolicy::isFrameratePriority() { |
| char frameratePriority[MESON_MODE_LEN] = { 0 }; |
| |
| if (DISPLAY_TYPE_TV == mDisplayType) { |
| MESON_LOGI("Current Device is TV, no framerate priority\n"); |
| return false; |
| } |
| return !getBootEnv(UBOOTENV_FRAMERATE_PRIORITY, frameratePriority) || |
| strcmp(frameratePriority, "true") == 0; |
| } |
| |
| bool ModePolicy::isSupport4K() { |
| return sys_get_bool_prop(PROP_SUPPORT_4K, true); |
| } |
| |
| bool ModePolicy::isSupport4K30Hz() { |
| return sys_get_bool_prop(PROP_SUPPORT_OVER_4K30, true); |
| } |
| |
| bool ModePolicy::isSupportDeepColor() { |
| return sys_get_bool_prop(PROP_DEEPCOLOR, true); |
| } |
| |
| bool ModePolicy::isLowPowerMode() { |
| return sys_get_bool_prop(LOW_POWER_DEFAULT_COLOR, false); |
| } |
| |
| |
| bool ModePolicy::isMboxSupportDV() { |
| return getDvSupportStatus(); |
| } |
| |
| int ModePolicy::parseHdmiHdrStatus() { |
| std::string HdrStatus; |
| getDisplayAttribute(DISPLAY_HDMI_HDR_STATUS, HdrStatus); |
| int hdrMode = atoi(HdrStatus.c_str()); |
| MESON_LOGI("hdr hdmi status: %s conversion result: %d", HdrStatus.c_str(),hdrMode); |
| return hdrMode; |
| } |
| |
| void ModePolicy::getHdrUserInfo(meson_hdr_info_t *data) { |
| if (!data) { |
| MESON_LOGE("%s data is NULL\n", __FUNCTION__); |
| return; |
| } |
| |
| int hdrStatus = parseHdmiHdrStatus(); |
| char hdr_force_mode[MESON_MODE_LEN] = {0}; |
| gethdrforcemode(hdr_force_mode); |
| data->hdr_force_mode = (meson_hdr_force_mode_e)atoi(hdr_force_mode); |
| |
| char hdr_policy[MESON_MODE_LEN] = {0}; |
| getHdrStrategy(hdr_policy); |
| data->hdr_policy = (meson_hdr_policy_e)atoi(hdr_policy); |
| |
| data->hdr_priority = (meson_hdr_priority_e)getHdrPriority(); |
| |
| MESON_LOGI("hdr_policy:%d, hdr_priority :%d(0x%x), hdr_force_mode:%d\n", |
| data->hdr_policy, |
| data->hdr_priority, data->hdr_priority, |
| data->hdr_force_mode); |
| |
| data->is_amdv_enable = isDVEnable(); |
| data->is_tv_supportDv = isTvSupportDV(); |
| if (data->hdr_policy == 1 && (hdrStatus == HDMI_HDR_STATUS_SDR)) { |
| data->is_tv_supportHDR = false; |
| } else { |
| data->is_tv_supportHDR = isTvSupportHDR(); |
| } |
| MESON_LOGI("tv_support_hdr status: %d hdrStatus %d", data->is_tv_supportHDR, hdrStatus); |
| data->is_hdr_resolution_priority = isHdrResolutionPriority(); |
| data->is_lowpower_mode = isLowPowerMode(); |
| |
| char ubootenv_amdv_type[MESON_MODE_LEN]; |
| bool ret = getBootEnv(UBOOTENV_USER_DV_TYPE, ubootenv_amdv_type); |
| if (ret) { |
| strcpy(data->ubootenv_dv_type, ubootenv_amdv_type); |
| } else if (isMboxSupportDV()) { |
| strcpy(data->ubootenv_dv_type, "1"); |
| } else { |
| strcpy(data->ubootenv_dv_type, "0"); |
| } |
| MESON_LOGI("ubootenv_dv_type:%s\n", data->ubootenv_dv_type); |
| } |
| |
| bool ModePolicy::initColorAttribute(char* supportedColorList, int len) { |
| int count = 0; |
| bool result = false; |
| |
| if (supportedColorList != NULL) { |
| memset(supportedColorList, 0, len); |
| } else { |
| MESON_LOGE("supportedColorList is NULL\n"); |
| return false; |
| } |
| |
| while (true) { |
| sysfs_get_string(DISPLAY_HDMI_DEEP_COLOR, supportedColorList, len); |
| if (strlen(supportedColorList) > 0) { |
| result = true; |
| break; |
| } |
| |
| if (count++ >= 5) { |
| break; |
| } |
| usleep(500000); |
| } |
| |
| return result; |
| } |
| |
| void ModePolicy::setFilterEdidList(std::map<int, std::string> filterEdidList) { |
| MESON_LOGI("FormatColorDepth setFilterEdidList size = %" PRIuFAST16 "", filterEdidList.size()); |
| mFilterEdid = filterEdidList; |
| } |
| |
| bool ModePolicy::isFilterEdid() { |
| if (mFilterEdid.empty()) |
| return false; |
| |
| std::string disPlayEdid = ""; |
| getDisplayAttribute(DISPLAY_EDID_ATTR, disPlayEdid); |
| MESON_LOGD("edid property: %s\n", disPlayEdid.c_str()); |
| |
| for (int i = 0; i < (int)mFilterEdid.size(); i++) { |
| if (!strncmp(mFilterEdid[i].c_str(), disPlayEdid.c_str(), strlen(mFilterEdid[i].c_str()))) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| |
| bool ModePolicy::isModeSupportDeepColorAttr(const char *mode, const char * color) { |
| char outputmode[MESON_MODE_LEN] = {0}; |
| |
| strcpy(outputmode, mode); |
| strcat(outputmode, color); |
| |
| if (isFilterEdid() && !strstr(color,"8bit")) { |
| MESON_LOGI("this mode has been filtered"); |
| return false; |
| } |
| |
| //try support or not |
| return sys_set_valid_mode(DISPLAY_HDMI_VALID_MODE, outputmode); |
| } |
| |
| bool ModePolicy::isSupportHdmiMode(const char *hdmi_mode, const char *supportedColorList) { |
| int length = 0; |
| const char **colorList = NULL; |
| |
| if (strstr(hdmi_mode, "2160p60hz") != NULL |
| || strstr(hdmi_mode,"2160p50hz") != NULL |
| || strstr(hdmi_mode,"smpte50hz") != NULL |
| || strstr(hdmi_mode,"smpte60hz") != NULL) { |
| |
| colorList = COLOR_ATTRIBUTE_LIST; |
| length = ARRAY_SIZE(COLOR_ATTRIBUTE_LIST); |
| |
| for (int i = 0; i < length; i++) { |
| if (strstr(supportedColorList, colorList[i]) != NULL) { |
| if (isModeSupportDeepColorAttr(hdmi_mode, colorList[i])) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } else { |
| colorList = COLOR_ATTRIBUTE_LIST_8BIT; |
| length = ARRAY_SIZE(COLOR_ATTRIBUTE_LIST_8BIT); |
| |
| for (int j = 0; j < length; j++) { |
| if (strstr(supportedColorList, colorList[j]) != NULL) { |
| if (isModeSupportDeepColorAttr(hdmi_mode, colorList[j])) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| } |
| |
| void ModePolicy::filterHdmiDispcap(meson_connector_info* data) { |
| char supportedColorList[MESON_MAX_STR_LEN]; |
| |
| if (!(initColorAttribute(supportedColorList, MESON_MAX_STR_LEN))) { |
| MESON_LOGE("initColorAttribute fail\n"); |
| return; |
| } |
| |
| meson_mode_info_t *modes_ptr = data->modes; |
| for (int i = 0; i < data->modes_size; i++) { |
| meson_mode_info_t *it = &modes_ptr[i]; |
| MESON_LOGD("before filtered Hdmi support: %s\n", it->name); |
| if (isSupportHdmiMode(it->name, supportedColorList)) { |
| MESON_LOGD("after filtered Hdmi support mode : %s\n", it->name); |
| } |
| } |
| |
| } |
| |
| int32_t ModePolicy::getConnectorData(struct meson_policy_in* data, hdmi_amdv_info_t *dinfo) { |
| if (!data) { |
| MESON_LOGE("%s data is NULL\n", __FUNCTION__); |
| return -EINVAL; |
| } |
| |
| getConnectorUserData(data, dinfo); |
| |
| //get hdmi dv_info |
| getDvCap(&data->hdr_info); |
| |
| // get Hdr info |
| getHdrUserInfo(&data->hdr_info); |
| |
| //hdmi info |
| getHdmiEdidStatus(data->con_info.edid_parsing, MESON_MODE_LEN); |
| |
| //three sink types: sink, repeater, none |
| data->con_info.sink_type = (meson_sink_type_e)getHdmiSinkType(); |
| MESON_LOGI("display sink type:%d [0:none, 1:sink, 2:repeater]\n", data->con_info.sink_type); |
| |
| if (HDMI_SINK_TYPE_NONE != data->con_info.sink_type) { |
| getSupportedModes(); |
| |
| //read hdmi dc_cap |
| char dc_cap[MESON_MAX_STR_LEN]; |
| getHdmiDcCap(dc_cap, MESON_MAX_STR_LEN); |
| strcpy(data->con_info.dc_cap, dc_cap); |
| } |
| |
| getDisplayMode(data->cur_displaymode); |
| |
| #if 0 |
| //filter hdmi disp_cap mode for compatibility |
| filterHdmiDispcap(&data->con_info); |
| #endif |
| |
| data->con_info.is_support4k = isSupport4K(); |
| data->con_info.is_support4k30HZ = isSupport4K30Hz(); |
| data->con_info.is_deepcolor = isSupportDeepColor(); |
| data->con_info.isframeratepriority = isFrameratePriority(); |
| |
| return 0; |
| } |
| |
| bool ModePolicy::setPolicy(int32_t policy) { |
| MESON_LOGD("setPolicy %d to %d", mPolicy, policy); |
| if (DISPLAY_TYPE_TV == mDisplayType) |
| return true; |
| |
| if (mPolicy == policy) |
| return true; |
| |
| switch (policy) { |
| case static_cast<int>(MESON_POLICY_BEST): |
| case static_cast<int>(MESON_POLICY_RESOLUTION): |
| case static_cast<int>(MESON_POLICY_FRAMERATE): |
| case static_cast<int>(MESON_POLICY_DV): |
| mPolicy = static_cast<meson_mode_policy>(policy); |
| break; |
| default: |
| MESON_LOGE("Set invalid policy:%d", policy); |
| return false; |
| } |
| |
| setSourceDisplay(OUTPUT_MODE_STATE_POWER); |
| applyDisplaySetting(false); |
| |
| return true; |
| } |
| |
| //TODO:: refactor to a thread to handle hotplug |
| void ModePolicy::onHotplug(bool connected) { |
| MESON_LOGD("ModePolicy handle hotplug:%d", connected); |
| //plugout or suspend,set dummy_l |
| if (!connected) { |
| setDisplay(OUTPUT_MODE_STATE_POWER); |
| return; |
| } |
| |
| //hdmi edid parse error and hpd = 1 |
| //set default reolsution and color format |
| if (isHdmiEdidParseOK() == false) { |
| setDefaultMode(); |
| return; |
| } |
| |
| //hdmi edid parse ok |
| setSourceDisplay(OUTPUT_MODE_STATE_POWER); |
| applyDisplaySetting(true); |
| } |
| |
| void ModePolicy::setActiveConfig(std::string mode) { |
| mReason = OUTPUT_CHANGE_BY_HWC; |
| MESON_LOGI("setDisplayed by hwc %s", mode.c_str()); |
| meson_mode_set_policy(mModeConType, MESON_POLICY_INVALID); |
| setSourceOutputMode(mode.c_str()); |
| meson_mode_set_policy(mModeConType, mPolicy); |
| mReason = OUTPUT_CHANGE_BY_INIT; |
| } |
| |
| int32_t ModePolicy::getPreferredBootConfig(std::string &config) { |
| if (DISPLAY_TYPE_TV == mDisplayType) { |
| char curMode[MESON_MODE_LEN] = {0}; |
| getDisplayMode(curMode); |
| config = curMode; |
| } else { |
| #if 0 |
| //1. get hdmi data |
| hdmi_data_t data; |
| |
| memset(&data, 0, sizeof(hdmi_data_t)); |
| getHdmiData(&data); |
| #endif |
| mConData.state = static_cast<meson_mode_state>(OUTPUT_MODE_STATE_INIT); |
| mConData.con_info.is_bestcolorspace = true; |
| |
| //2. scene logic process |
| meson_mode_set_policy(mModeConType, MESON_POLICY_RESOLUTION); |
| meson_mode_set_policy_input(mModeConType, &mConData); |
| meson_mode_get_policy_output(mModeConType, &mSceneOutInfo); |
| |
| config = mSceneOutInfo.displaymode; |
| } |
| |
| MESON_LOGI("getPreferredDisplayConfig [%s]", config.c_str()); |
| meson_mode_set_policy(mModeConType, mPolicy); |
| return 0; |
| } |
| |
| int32_t ModePolicy::setBootConfig(std::string &config) { |
| MESON_LOGI("set boot display config to %s\n", config.c_str()); |
| setBootEnv(UBOOTENV_ISBESTMODE, "false"); |
| if (mConnectorType == CONN_TYPE_HDMI) |
| setBootEnv(UBOOTENV_HDMIMODE, config.c_str()); |
| |
| return 0; |
| } |
| |
| int32_t ModePolicy::clearBootConfig() { |
| MESON_LOGI("clear boot display \n"); |
| setBootEnv(UBOOTENV_ISBESTMODE, "true"); |
| |
| //save hdmi resolution to env |
| // setBootEnv(UBOOTENV_HDMIMODE, "none"); |
| |
| return 0; |
| } |
| |
| int32_t ModePolicy::clearUserDisplayConfig() { |
| SYS_LOGI("clear user display config\n"); |
| |
| //clear user color format |
| setBootEnv(UBOOTENV_USER_COLORATTRIBUTE, "none"); |
| //clear user dv |
| setBootEnv(UBOOTENV_USER_DV_TYPE, "none"); |
| |
| //2. set hdmi mode for trigger setting |
| getDisplayMode(mCurrentMode); |
| setSourceOutputMode(mCurrentMode); |
| |
| return 0; |
| } |
| |
| int32_t ModePolicy::setColorSpace(std::string &colorspace) { |
| SYS_LOGI("user change color space to %s\n", colorspace.c_str()); |
| setBootEnv(UBOOTENV_USER_COLORATTRIBUTE, colorspace.c_str()); |
| |
| getDisplayMode(mCurrentMode); |
| saveDeepColorAttr(mCurrentMode, colorspace.c_str()); |
| |
| //2. set hdmi mode for trigger setting |
| setSourceOutputMode(mCurrentMode); |
| |
| return 0; |
| } |
| |
| void ModePolicy::getModes(drmModeConnector *connector, |
| std::map<uint32_t, drm_mode_info_t> &modes) |
| { |
| if (!connector) |
| return; |
| |
| if (connector->connection != DRM_MODE_CONNECTED) |
| return; |
| |
| std::string s_max_output_size; |
| getDisplayAttribute(DISPLAY_CRTC_MAX_OUTPUT_SIZE, s_max_output_size); |
| int max_output_size = 0; |
| int max_output_size_w = 0; |
| int max_output_size_h = 0; |
| max_output_size = atoi(s_max_output_size.c_str()); |
| max_output_size_w = max_output_size & 0xffff; |
| max_output_size_h = max_output_size >> 16; |
| MESON_LOGD("DISPLAY_CRTC_MAX_OUTPUT_SIZE:%s (%dx%d)", |
| s_max_output_size.c_str(), max_output_size_w, max_output_size_h); |
| |
| mConnecterModes.clear(); |
| /*add new display mode list.*/ |
| drmModeModeInfoPtr drmModes = connector->modes; |
| drm_mode_info_t modeInfo; |
| memset(&modeInfo, 0, sizeof(modeInfo)); |
| for (int i = 0;i < connector->count_modes; i++) { |
| if (max_output_size_w != 0 && max_output_size_h != 0 |
| && drmModes[i].hdisplay > max_output_size_w |
| && drmModes[i].vdisplay > max_output_size_h ) { |
| MESON_LOGD("mode:%dx%d not support", drmModes[i].hdisplay, drmModes[i].vdisplay); |
| continue; |
| } |
| strncpy(modeInfo.name, drmModes[i].name, DRM_DISPLAY_MODE_LEN - 1); |
| modeInfo.pixelW = drmModes[i].hdisplay; |
| modeInfo.pixelH = drmModes[i].vdisplay; |
| if (connector->mmWidth != 0 && connector->mmHeight != 0) { |
| modeInfo.dpiX = (modeInfo.pixelW * 25.4f) / connector->mmWidth * 1000; |
| modeInfo.dpiY = (modeInfo.pixelH * 25.4f) / connector->mmHeight * 1000; |
| } |
| modeInfo.refreshRate = drmModes[i].vrefresh; |
| modeInfo.flags = drmModes[i].flags; |
| |
| bool bNonFractionMode = false; |
| if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) { |
| // default add frac refresh rate config, like 23.976hz, 29.97hz... |
| if (modeInfo.refreshRate == REFRESH_24kHZ |
| || modeInfo.refreshRate == REFRESH_30kHZ |
| || modeInfo.refreshRate == REFRESH_60kHZ |
| || modeInfo.refreshRate == REFRESH_120kHZ |
| || modeInfo.refreshRate == REFRESH_240kHZ) { |
| if (mFracMode == MODE_ALL || mFracMode == MODE_FRACTION) { |
| drm_mode_info_t fracMode = modeInfo; |
| fracMode.refreshRate = (modeInfo.refreshRate * 1000) / (float)1001; |
| fracMode.groupId = mConnecterModes.size(); |
| mConnecterModes.emplace(mConnecterModes.size(), fracMode); |
| MESON_LOGD("add fraction display mode (%s)", fracMode.name); |
| } |
| } else { |
| bNonFractionMode = true; |
| } |
| } |
| |
| if (connector->connector_type != DRM_MODE_CONNECTOR_HDMIA || |
| mFracMode == MODE_ALL || mFracMode == MODE_NON_FRACTION) { |
| bNonFractionMode = true; |
| } |
| // drm only send frame rate (int)59hz, its real frac refresh rate is 59.94hz |
| if (modeInfo.refreshRate == 59.00) { |
| modeInfo.refreshRate = (60 * 1000) / (float)1001; |
| } |
| |
| if (bNonFractionMode) { |
| // add normal refresh rate config, like 24hz, 30hz... |
| modeInfo.groupId = mConnecterModes.size(); |
| mConnecterModes.emplace(mConnecterModes.size(), modeInfo); |
| } |
| MESON_LOGD("add display mode (%s-%s, %dx%d, %f)", |
| drmModes[i].name, modeInfo.name, |
| modeInfo.pixelW, modeInfo.pixelH, modeInfo.refreshRate); |
| } |
| modes = mConnecterModes; |
| } |
| |
| int32_t ModePolicy::bindConnector(drmModeConnector *connector) { |
| MESON_ASSERT(connector, "ModePolicy bindConnector get null connector!!"); |
| |
| MESON_LOGI("bindConnector: mConnector: %p\n", mConnector); |
| std::map<uint32_t, drm_mode_info_t> modes; |
| getModes(connector, modes); |
| |
| mConnector = connector; |
| switch (mConnector->connector_type) { |
| case DRM_MODE_CONNECTOR_HDMIA: |
| mDisplayType = DISPLAY_TYPE_MBOX; |
| mConnectorType = CONN_TYPE_HDMI; |
| mModeConType = MESON_MODE_HDMI; |
| break; |
| case LEGACY_NON_DRM_CONNECTOR_PANEL: |
| case DRM_MODE_CONNECTOR_LVDS: |
| case DRM_MODE_CONNECTOR_MESON_LVDS_A: |
| case DRM_MODE_CONNECTOR_MESON_LVDS_B: |
| case DRM_MODE_CONNECTOR_MESON_LVDS_C: |
| case DRM_MODE_CONNECTOR_MESON_VBYONE_A: |
| case DRM_MODE_CONNECTOR_MESON_VBYONE_B: |
| case DRM_MODE_CONNECTOR_MESON_MIPI_A: |
| case DRM_MODE_CONNECTOR_MESON_MIPI_B: |
| case DRM_MODE_CONNECTOR_MESON_EDP_A: |
| case DRM_MODE_CONNECTOR_MESON_EDP_B: |
| mDisplayType = DISPLAY_TYPE_TV; |
| mConnectorType = CONN_TYPE_PANEL; |
| mModeConType = MESON_MODE_PANEL; |
| break; |
| case DRM_MODE_CONNECTOR_TV: |
| mDisplayType = DISPLAY_TYPE_MBOX; |
| mConnectorType = CONN_TYPE_CVBS; |
| mModeConType = MESON_MODE_HDMI; |
| break; |
| default: |
| MESON_LOGE("bindConnector unknown connector type:%d", mConnector->connector_type); |
| mDisplayType = DISPLAY_TYPE_MBOX; |
| mConnectorType = CONN_TYPE_HDMI; |
| mModeConType = MESON_MODE_HDMI; |
| break; |
| } |
| |
| return 0; |
| } |
| |
| int32_t ModePolicy::bindCrtc(drmModeCrtcPtr crtc) { |
| mCrtc = crtc; |
| mAdapter->initDisplayAttributeInfo(mCrtc, mConnector); |
| updateHdrCaps(); |
| return 0; |
| } |
| |
| /* * |
| * @Description: init dv graphics priority when bootup. |
| * */ |
| void ModePolicy::initGraphicsPriority() { |
| char mode[MESON_MODE_LEN] = {0}; |
| char defVal[MESON_MODE_LEN] = {"1"}; |
| |
| sys_get_string_prop_default(PROP_AMDV_PRIORITY, mode, defVal); |
| setDisplayAttribute(DISPLAY_AMDV_GRAPHICS_PRIORITY, mode); |
| sys_set_prop(PROP_AMDV_PRIORITY, mode); |
| } |
| |
| |
| /* * |
| * @Description: set hdr mode |
| * @params: mode "0":off "1":on "2":auto |
| * */ |
| void ModePolicy::setHdrMode(const char* mode) { |
| if ((atoi(mode) >= 0) && (atoi(mode) <= 2)) { |
| MESON_LOGI("setHdrMode state: %s\n", mode); |
| setDisplayAttribute(DISPLAY_HDR_MODE, mode); |
| sys_set_prop(PROP_HDR_MODE_STATE, mode); |
| } |
| } |
| |
| /* * |
| * @Description: set sdr mode |
| * @params: mode "0":off "2":auto |
| * */ |
| void ModePolicy::setSdrMode(const char* mode) { |
| if ((atoi(mode) == 0) || atoi(mode) == 2) { |
| MESON_LOGI("setSdrMode state: %s\n", mode); |
| setDisplayAttribute(DISPLAY_SDR_MODE, mode); |
| sys_set_prop(PROP_SDR_MODE_STATE, mode); |
| setBootEnv(UBOOTENV_SDR2HDR, (char *)mode); |
| } |
| } |
| |
| |
| void ModePolicy::initHdrSdrMode() { |
| char mode[MESON_MODE_LEN] = {0}; |
| char defVal[MESON_MODE_LEN] = {HDR_MODE_AUTO}; |
| sys_get_string_prop_default(PROP_HDR_MODE_STATE, mode, defVal); |
| setHdrMode(mode); |
| memset(mode, 0, sizeof(mode)); |
| bool flag = sys_get_bool_prop(PROP_ENABLE_SDR2HDR, false); |
| if (flag & isDVEnable()) { |
| strcpy(mode, SDR_MODE_OFF); |
| } else { |
| strcpy(defVal, flag ? SDR_MODE_AUTO : SDR_MODE_OFF); |
| sys_get_string_prop_default(PROP_SDR_MODE_STATE, mode, defVal); |
| } |
| setSdrMode(mode); |
| } |
| |
| bool ModePolicy::checkDVStatusChanged(int state) { |
| std::string curDvEnable = ""; |
| std::string curDvLLPolicy = ""; |
| int curDvMode = -1; |
| |
| getDisplayAttribute(DISPLAY_AMDV_ENABLE, curDvEnable); |
| getDisplayAttribute(DISPLAY_AMDV_LL_POLICY, curDvLLPolicy); |
| MESON_LOGI("curDvEnable %s, curDvLLPolicy %s!!\n", curDvEnable.c_str(), curDvLLPolicy.c_str()); |
| |
| if (!strcmp(curDvEnable.c_str(), AMDV_DISABLE) || |
| !strcmp(curDvEnable.c_str(), "0")) |
| curDvMode = AMDV_SET_DISABLE; |
| else if (!strcmp(curDvLLPolicy.c_str(), "0")) |
| curDvMode = AMDV_SET_ENABLE; |
| else if (!strcmp(curDvLLPolicy.c_str(), "1")) |
| curDvMode = AMDV_SET_ENABLE_LL_YUV; |
| else if (!strcmp(curDvLLPolicy.c_str(), "2")) |
| curDvMode = AMDV_SET_ENABLE_LL_RGB; |
| |
| MESON_LOGI("curDvMode %d, want DvMode %d\n", curDvMode, state); |
| |
| if (curDvMode != state) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| //get edid crc value to check edid change |
| bool ModePolicy::isEdidChange() { |
| char edid[MESON_MAX_STR_LEN] = {0}; |
| char crcvalue[MESON_MAX_STR_LEN] = {0}; |
| unsigned int crcheadlength = strlen(DEFAULT_EDID_CRCHEAD); |
| sysfs_get_string(DISPLAY_EDID_VALUE, edid, MESON_MAX_STR_LEN); |
| char *p = strstr(edid, DEFAULT_EDID_CRCHEAD); |
| if (p != NULL && strlen(p) > crcheadlength) { |
| p += crcheadlength; |
| if (!getBootEnv(UBOOTENV_EDIDCRCVALUE, crcvalue) || strncmp(p, crcvalue, strlen(p))) { |
| MESON_LOGI("update edidcrc: %s->%s\n", crcvalue, p); |
| setBootEnv(UBOOTENV_EDIDCRCVALUE, p); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| void ModePolicy::saveDeepColorAttr(const char* mode, const char* dcValue) { |
| char ubootvar[100] = {0}; |
| sprintf(ubootvar, "ubootenv.var.%s_deepcolor", mode); |
| setBootEnv(ubootvar, (char *)dcValue); |
| } |
| |
| void ModePolicy::saveHdmiParamToEnv() { |
| char outputMode[MESON_MODE_LEN] = {0}; |
| char dvenable[MESON_MODE_LEN] = {0}; |
| |
| getDisplayMode(outputMode); |
| if (strlen(mDvInfo.amdv_enable) > 0) |
| strcpy(dvenable, mDvInfo.amdv_enable); |
| |
| // 1. check whether the TV changed or not, if changed save crc |
| if (isEdidChange()) { |
| MESON_LOGD("tv sink changed\n"); |
| } |
| |
| // 2. save coloattr/hdmimode to bootenv if mode is not null or dummy_l |
| if (strstr(outputMode, "cvbs") != NULL) { |
| setBootEnv(UBOOTENV_CVBSMODE, (char *)outputMode); |
| } else if (strcmp(outputMode, "null") && strcmp(outputMode, "dummy_l")) { |
| std::string colorAttr; |
| char colorDepth[MESON_MODE_LEN] = {0}; |
| char colorSpace[MESON_MODE_LEN] = {0}; |
| char dvstatus[MESON_MODE_LEN] = {0}; |
| char hdr_policy[MESON_MODE_LEN] = {0}; |
| // 2.1 save color attr |
| getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, colorAttr); |
| saveDeepColorAttr(outputMode, colorAttr.c_str()); |
| setBootEnv(UBOOTENV_COLORATTRIBUTE, colorAttr.c_str()); |
| //colorDepth&&colorSpace is used for uboot hdmi to find |
| //best color attributes for the selected hdmi mode when TV changed |
| char defVal[MESON_MODE_LEN] = {"8"}; |
| sys_get_string_prop_default(PROP_DEEPCOLOR_CTL, colorDepth, defVal); |
| strcpy(defVal, "auto"); |
| sys_get_string_prop_default(PROP_PIXFMT, colorSpace, defVal); |
| setBootEnv(UBOOTENV_HDMICOLORDEPTH, colorDepth); |
| setBootEnv(UBOOTENV_HDMICOLORSPACE, colorSpace); |
| |
| // 2.2 save output mode,removed, we use hdmimode for hdmi. |
| // 2.3 save dv status/dv_type |
| // In follow sink mode: 0:disable 1:STD(or enable dv) 2:LL YUV 3: LL RGB |
| // In follow source mode: dv is disable in uboot. |
| if (isMboxSupportDV()) { |
| char hdr_force_mode[MESON_MODE_LEN] = {0}; |
| memset(hdr_force_mode, 0, MESON_MODE_LEN); |
| getBootEnv(UBOOTENV_HDR_FORCE_MODE, hdr_force_mode); |
| getHdrStrategy(hdr_policy); |
| if (!strcmp(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]) || |
| (!strcmp(hdr_policy, AMDV_POLICY_FORCE_MODE) && !strcmp(hdr_force_mode, FORCE_HDR10))) { |
| sprintf(dvstatus, "%d", 0); |
| } else { |
| sprintf(dvstatus, "%d", mSceneOutInfo.amdv_type); |
| } |
| setBootEnv(UBOOTENV_DOLBYSTATUS, dvstatus); |
| |
| if (strlen(dvenable) > 0) |
| setBootEnv(UBOOTENV_DV_ENABLE, dvenable); |
| |
| MESON_LOGI("dvstatus %s dv_type %d dv_enable %s hdr_policy %s hdr_force_mode %s \n", |
| dvstatus, mSceneOutInfo.amdv_type, mDvInfo.amdv_enable, hdr_policy, hdr_force_mode); |
| |
| } else { |
| MESON_LOGI("MBOX is not support dv, dvstatus %s dv_type %d dv_enable %s\n", |
| dvstatus, mSceneOutInfo.amdv_type, mDvInfo.amdv_enable); |
| } |
| |
| MESON_LOGI("colorattr: %s, outputMode %s, cd %s, cs %s\n", |
| colorAttr.c_str(), outputMode, colorDepth, colorSpace); |
| } |
| } |
| |
| bool ModePolicy::updateEnv() |
| { |
| if (mDisplayType == DISPLAY_TYPE_MBOX) |
| saveHdmiParamToEnv(); |
| return true; |
| } |
| |
| void ModePolicy::enableDV(int DvMode) { |
| if (isMboxSupportDV() == false) { |
| MESON_LOGI("This platform is not support dv or has no dv ko"); |
| return; |
| } |
| MESON_LOGI("DvMode %d", DvMode); |
| |
| strcpy(mDvInfo.amdv_enable, "1"); |
| |
| //if TV |
| if (DISPLAY_TYPE_TV == mDisplayType) { |
| setHdrMode(HDR_MODE_OFF); |
| setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FOLLOW_SINK); |
| } |
| |
| //if OTT |
| char hdr_policy[MESON_MODE_LEN] = {0}; |
| getHdrStrategy(hdr_policy); |
| if ((DISPLAY_TYPE_MBOX == mDisplayType) || (DISPLAY_TYPE_REPEATER == mDisplayType)) { |
| switch (DvMode) { |
| case AMDV_SET_ENABLE: |
| MESON_LOGI("Dv set Mode [DV_RGB_444_8BIT]\n"); |
| setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0"); |
| break; |
| case AMDV_SET_ENABLE_LL_YUV: |
| MESON_LOGI("Dv set Mode [LL_YCbCr_422_12BIT]\n"); |
| setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0"); |
| setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "1"); |
| break; |
| case AMDV_SET_ENABLE_LL_RGB: |
| setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0"); |
| setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "2"); |
| break; |
| default: |
| setDisplayAttribute(DISPLAY_AMDV_LL_POLICY, "0"); |
| } |
| |
| if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) { |
| setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]); |
| if (isDVEnable()) { |
| setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]); |
| } |
| } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) { |
| setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]); |
| if (isDVEnable()) { |
| setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]); |
| } |
| } else if (strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) { |
| setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]); |
| if (isDVEnable()) { |
| setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE); |
| } |
| } |
| } |
| |
| setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_ENABLE); |
| if (strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) { |
| char hdr_force_mode[MESON_MODE_LEN] = {0}; |
| gethdrforcemode(hdr_force_mode); |
| if (strstr(hdr_force_mode, FORCE_AMDV)) { |
| setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_AMDV); |
| } else if (strstr(hdr_force_mode, FORCE_HDR10)) { |
| setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_HDR10); |
| } else if (strstr(hdr_force_mode, AMDV_DISABLE_FORCE_SDR)) { |
| // 8bit or not |
| std::string cur_ColorAttribute; |
| getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute); |
| if (cur_ColorAttribute.find("8bit", 0) != std::string::npos) { |
| setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_8BIT); |
| } else { |
| setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_10BIT); |
| } |
| } |
| } else { |
| int amdv_prop = DvMode == AMDV_SET_ENABLE_LL_YUV ? 1 : 0; |
| setDisplayAttribute(DISPLAY_AMDV_MODE, to_string(amdv_prop)); |
| } |
| |
| if (DISPLAY_TYPE_TV == mDisplayType) { |
| setHdrMode(HDR_MODE_AUTO); |
| } |
| |
| initGraphicsPriority(); |
| } |
| |
| void ModePolicy::disableDV(int DvMode) { |
| //char tvmode[MESON_MODE_LEN] = {0}; |
| int check_status_count = 0; |
| [[maybe_unused]] int amdv_type = DvMode; |
| |
| MESON_LOGI("amdv_type %d", amdv_type); |
| strcpy(mDvInfo.amdv_enable, "0"); |
| |
| //2. update sysfs |
| char hdr_policy[MESON_MODE_LEN] = {0}; |
| getHdrStrategy(hdr_policy); |
| |
| if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) { |
| setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]); |
| } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) { |
| setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]); |
| } |
| |
| setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE); |
| setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_MODE_BYPASS); |
| usleep(100000);//100ms |
| std::string dvstatus = ""; |
| getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus); |
| |
| if (strcmp(dvstatus.c_str(), BYPASS_PROCESS)) { |
| while (++check_status_count <30) { |
| usleep(20000);//20ms |
| getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus); |
| if (!strcmp(dvstatus.c_str(), BYPASS_PROCESS)) { |
| break; |
| } |
| } |
| } |
| |
| MESON_LOGI("dvstatus %s, check_status_count [%d]", dvstatus.c_str(), check_status_count); |
| setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_DISABLE); |
| |
| if (DISPLAY_TYPE_TV == mDisplayType) { |
| setHdrMode(HDR_MODE_AUTO); |
| } |
| |
| setSdrMode(SDR_MODE_AUTO); |
| } |
| |
| void ModePolicy::getPosition(const char* curMode, int *position) { |
| char keyValue[20] = {0}; |
| char ubootvar[100] = {0}; |
| int defaultWidth = 0; |
| int defaultHeight = 0; |
| std::map<uint32_t, drm_mode_info_t> connecterModeList; |
| |
| drm_mode_info_t mode = { |
| "null", |
| 0, 0, |
| 0, 0, |
| 60.0, |
| 0 |
| }; |
| |
| if (mConnector->connection == DRM_MODE_CONNECTED) { |
| getModes(mConnector, connecterModeList); |
| |
| for (auto it = connecterModeList.begin(); it != connecterModeList.end(); it++) { |
| if (mConnector->connector_type == DRM_MODE_CONNECTOR_TV) { |
| if (strstr(curMode, it->second.name)) { |
| strcpy(keyValue, curMode); |
| mode = it->second; |
| break; |
| } |
| } else { |
| if (strstr(curMode, it->second.name)) { |
| if (strstr(it->second.name, MODE_4K2KSMPTE_PREFIX)) { |
| strcpy(keyValue, "4k2ksmpte"); |
| } else if (strstr(it->second.name, MODE_PANEL)) { |
| strcpy(keyValue, MODE_PANEL); |
| } else if (strchr(curMode,'p')) { |
| strncpy(keyValue, curMode, strchr(curMode,'p') - curMode + 1); |
| } else if (strchr(curMode,'i')){ |
| strncpy(keyValue, curMode, strchr(curMode,'i') - curMode + 1); |
| } |
| mode = it->second; |
| break; |
| } |
| } |
| } |
| } |
| |
| if (keyValue[0] != '0') { |
| defaultWidth = mode.pixelW; |
| defaultHeight = mode.pixelH; |
| } else { |
| strcpy(keyValue, MODE_1080P_PREFIX); |
| defaultWidth = FULL_WIDTH_1080; |
| defaultHeight = FULL_HEIGHT_1080; |
| } |
| |
| pthread_mutex_lock(&mEnvLock); |
| sprintf(ubootvar, "ubootenv.var.%s_x", keyValue); |
| position[0] = getBootenvInt(ubootvar, 0); |
| sprintf(ubootvar, "ubootenv.var.%s_y", keyValue); |
| position[1] = getBootenvInt(ubootvar, 0); |
| sprintf(ubootvar, "ubootenv.var.%s_w", keyValue); |
| position[2] = getBootenvInt(ubootvar, defaultWidth); |
| sprintf(ubootvar, "ubootenv.var.%s_h", keyValue); |
| position[3] = getBootenvInt(ubootvar, defaultHeight); |
| |
| 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]); |
| |
| pthread_mutex_unlock(&mEnvLock); |
| |
| } |
| |
| void ModePolicy::setPosition(const char* curMode, int left, int top, int width, int height) { |
| char x[512] = {0}; |
| char y[512] = {0}; |
| char w[512] = {0}; |
| char h[512] = {0}; |
| sprintf(x, "%d", left); |
| sprintf(y, "%d", top); |
| sprintf(w, "%d", width); |
| sprintf(h, "%d", height); |
| |
| MESON_LOGI("%s curMode:%s left:%d top:%d width:%d height:%d\n", __FUNCTION__, curMode, left, top, width, height); |
| |
| char keyValue[20] = {0}; |
| char ubootvar[100] = {0}; |
| bool find = false; |
| std::map<uint32_t, drm_mode_info_t> connecterModeList; |
| |
| if (mConnector->connection == DRM_MODE_CONNECTED) { |
| getModes(mConnector, connecterModeList); |
| |
| for (auto it = connecterModeList.begin(); it != connecterModeList.end(); it++) { |
| if (mConnector->connector_type == DRM_MODE_CONNECTOR_TV) { |
| if (strstr(curMode, it->second.name)) { |
| strcpy(keyValue, curMode); |
| find = true; |
| break; |
| } |
| } else { |
| if (strstr(curMode, it->second.name)) { |
| if (strstr(it->second.name, MODE_4K2KSMPTE_PREFIX)) { |
| strcpy(keyValue, "4k2ksmpte"); |
| find = true; |
| } else if (strstr(it->second.name, MODE_PANEL)) { |
| strcpy(keyValue, MODE_PANEL); |
| find = true; |
| } else if (strchr(curMode,'p')) { |
| strncpy(keyValue, curMode, strchr(curMode,'p') - curMode + 1); |
| find = true; |
| } else if (strchr(curMode,'i')){ |
| strncpy(keyValue, curMode, strchr(curMode,'i') - curMode + 1); |
| find = true; |
| } |
| break; |
| } |
| } |
| } |
| } |
| |
| if (!find) |
| return; |
| |
| mAdapter->setDisplayRect(left, top, width , height); |
| } |
| |
| void ModePolicy::setDigitalMode(const char* mode) { |
| if (mode == NULL) return; |
| |
| if (!strcmp("PCM", mode)) { |
| sysfs_set_string(AUDIO_DSP_DIGITAL_RAW, "0"); |
| sysfs_set_string(AV_HDMI_CONFIG, "audio_on"); |
| } else if (!strcmp("SPDIF passthrough", mode)) { |
| sysfs_set_string(AUDIO_DSP_DIGITAL_RAW, "1"); |
| sysfs_set_string(AV_HDMI_CONFIG, "audio_on"); |
| } else if (!strcmp("HDMI passthrough", mode)) { |
| sysfs_set_string(AUDIO_DSP_DIGITAL_RAW, "2"); |
| sysfs_set_string(AV_HDMI_CONFIG, "audio_on"); |
| } |
| } |
| |
| bool ModePolicy::getDisplayMode(char* mode) { |
| bool ret = false; |
| |
| if (mode != NULL) { |
| ret = mAdapter->getDisplayMode(mode); |
| MESON_LOGI("%s mode:%s\n", __FUNCTION__, mode); |
| } else { |
| MESON_LOGE("%s mode is NULL\n", __FUNCTION__); |
| } |
| |
| return ret; |
| } |
| |
| //set hdmi output mode |
| int32_t ModePolicy::setDisplayMode(std::string &mode) { |
| MESON_LOGI("%s mode:%s\n", __FUNCTION__, mode.c_str()); |
| mAdapter->setDisplayMode(mode); |
| return 0; |
| } |
| |
| int32_t ModePolicy::setDisplayMode(const char *mode) { |
| if (!mode) { |
| MESON_LOGE("ModePolicy::setDisplayMode null mode"); |
| return -EINVAL; |
| } |
| std::string displayMode(mode); |
| return setDisplayMode(displayMode); |
| } |
| |
| bool ModePolicy::setDisplayAttribute(const std::string cmd, const std::string attribute) { |
| return mAdapter->setDisplayAttribute(cmd, attribute); |
| } |
| bool ModePolicy::getDisplayAttribute(const std::string cmd, std::string& attribute) { |
| return mAdapter->getDisplayAttribute(cmd, attribute); |
| } |
| |
| bool ModePolicy::isMatchMode(char* curmode, const char* outputmode) { |
| bool ret = false; |
| char tmpMode[MESON_MODE_LEN] = {0}; |
| |
| char *pCmp = curmode; |
| //check line feed key |
| char *pos = strchr(pCmp, 0x0a); |
| if (NULL == pos) { |
| //check return key |
| char *pos = strchr(pCmp, 0x0d); |
| if (NULL == pos) { |
| strcpy(tmpMode, pCmp); |
| } else { |
| strncpy(tmpMode, pCmp, pos - pCmp); |
| } |
| } else { |
| strncpy(tmpMode, pCmp, pos - pCmp); |
| } |
| |
| MESON_LOGI("curmode:%s, tmpMode:%s, outputmode:%s\n", curmode, tmpMode, outputmode); |
| |
| if (!strcmp(tmpMode, outputmode)) { |
| ret = true; |
| } |
| |
| return ret; |
| } |
| |
| bool ModePolicy::isTvSupportALLM() { |
| char allm_mode_cap[PROP_VALUE_MAX]; |
| memset(allm_mode_cap, 0, PROP_VALUE_MAX); |
| int ret = 0; |
| |
| sysfs_get_string(AUTO_LOW_LATENCY_MODE_CAP, allm_mode_cap, PROP_VALUE_MAX); |
| |
| for (int i = 0; i < ARRAY_SIZE(ALLM_MODE_CAP); i++) { |
| if (!strncmp(allm_mode_cap, ALLM_MODE_CAP[i], strlen(ALLM_MODE_CAP[i]))) { |
| ret = i; |
| } |
| } |
| |
| return (ret == 1) ? true : false; |
| } |
| |
| bool ModePolicy::getContentTypeSupport(const char* type) { |
| char content_type_cap[MESON_MAX_STR_LEN] = {0}; |
| sysfs_get_string(HDMI_CONTENT_TYPE_CAP, content_type_cap, MESON_MAX_STR_LEN); |
| if (strstr(content_type_cap, type)) { |
| MESON_LOGI("getContentTypeSupport: %s is true", type); |
| return true; |
| } |
| |
| MESON_LOGI("getContentTypeSupport: %s is false", type); |
| return false; |
| } |
| |
| bool ModePolicy::getGameContentTypeSupport() { |
| return getContentTypeSupport(CONTENT_TYPE_CAP[3]); |
| } |
| |
| bool ModePolicy::getSupportALLMContentTypeList(std::vector<std::string> *supportModes) { |
| if (isTvSupportALLM()) { |
| (*supportModes).push_back(std::string("allm")); |
| } |
| |
| for (int i = 0; i < ARRAY_SIZE(CONTENT_TYPE_CAP); i++) { |
| if (getContentTypeSupport(CONTENT_TYPE_CAP[i])) { |
| (*supportModes).push_back(std::string(CONTENT_TYPE_CAP[i])); |
| } |
| } |
| |
| return true; |
| } |
| |
| |
| void ModePolicy::setTvDVEnable() { |
| //if TV |
| setHdrMode(HDR_MODE_OFF); |
| setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FOLLOW_SINK); |
| |
| usleep(100000);//100ms |
| setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_ENABLE); |
| usleep(100000);//100ms |
| |
| setHdrMode(HDR_MODE_AUTO); |
| |
| initGraphicsPriority(); |
| } |
| |
| void ModePolicy::setTvDVDisable() { |
| int check_status_count = 0; |
| |
| //2. update sysfs |
| setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]); |
| |
| setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE); |
| setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_MODE_BYPASS); |
| usleep(100000);//100ms |
| std::string dvstatus = ""; |
| getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus); |
| |
| if (strcmp(dvstatus.c_str(), BYPASS_PROCESS)) { |
| while (++check_status_count <30) { |
| usleep(20000);//20ms |
| getDisplayAttribute(DISPLAY_AMDV_STATUS, dvstatus); |
| if (!strcmp(dvstatus.c_str(), BYPASS_PROCESS)) { |
| break; |
| } |
| } |
| } |
| |
| MESON_LOGI("dvstatus %s, check_status_count [%d]", dvstatus.c_str(), check_status_count); |
| setDisplayAttribute(DISPLAY_AMDV_ENABLE, AMDV_DISABLE); |
| |
| setHdrMode(HDR_MODE_AUTO); |
| setSdrMode(SDR_MODE_AUTO); |
| } |
| |
| |
| int32_t ModePolicy::setDvMode(std::string &amdv_mode) { |
| MESON_LOGI("%s dv mode:%s", __FUNCTION__, amdv_mode.c_str()); |
| |
| if (DISPLAY_TYPE_TV == mDisplayType) { |
| //1. update prop |
| strcpy(mConData.hdr_info.ubootenv_dv_type, amdv_mode.c_str()); |
| |
| //2. apply to driver |
| if (strstr(amdv_mode.c_str(), "0")) { |
| strcpy(mDvInfo.amdv_enable, "0"); |
| setTvDVDisable(); |
| } else { |
| strcpy(mDvInfo.amdv_enable, "1"); |
| setTvDVEnable(); |
| } |
| |
| //3. save env |
| setBootEnv(UBOOTENV_DV_ENABLE, mDvInfo.amdv_enable); |
| } else { |
| //1. update dv env |
| strcpy(mConData.hdr_info.ubootenv_dv_type, amdv_mode.c_str()); |
| |
| if (strstr(amdv_mode.c_str(), "0")) { |
| strcpy(mDvInfo.amdv_enable, "0"); |
| } else { |
| strcpy(mDvInfo.amdv_enable, "1"); |
| } |
| |
| //Save user prefer dv mode only user change dv through UI |
| setBootEnv(UBOOTENV_USER_DV_TYPE, mConData.hdr_info.ubootenv_dv_type); |
| setBootEnv(UBOOTENV_DV_ENABLE, mDvInfo.amdv_enable); |
| setBootEnv(UBOOTENV_DOLBYSTATUS, amdv_mode.c_str()); |
| |
| //2. set hdmi mode for trigger setting |
| setSourceOutputMode(mCurrentMode); |
| } |
| |
| return 0; |
| } |
| |
| |
| /* * |
| * @Description: this is a temporary solution, should be revert when android.hardware.graphics.composer@2.4 finished |
| * set the ALLM_Mode |
| * @params: "0": ALLM disable (VSIF still contain allm info) |
| * "1": ALLM enable |
| * "-1":really disable ALLM (VSIF don't contain allm info) |
| * */ |
| void ModePolicy::setALLMMode(int state) { |
| /*************************************************************** |
| * Comment for special solution in this func * |
| *************************************************************** |
| * * |
| * In HDMI Standard only 0 to disable ALLM and 1 to enable ALLM* |
| * but ALLM and DV share the same bit in VSIF * |
| * it cause conflict * |
| * * |
| * So in amlogic special solution: * |
| * we add -1 to * |
| * 1: disable ALLM * |
| * 2: clean ALLM info in VSIF conflict bit * |
| * when user set 0 to ALLM * |
| * we will force change 0 into -1 here * |
| * * |
| ***************************************************************/ |
| |
| if (!isTvSupportALLM()) { |
| SYS_LOGI("setALLMMode: TV not support ALLM\n"); |
| return; |
| } |
| |
| int perState = -1; |
| char cur_allm_state[MESON_MODE_LEN] = {0}; |
| sysfs_get_string(AUTO_LOW_LATENCY_MODE, cur_allm_state, MESON_MODE_LEN); |
| perState = atoi(cur_allm_state); |
| if (perState == state) { |
| SYS_LOGI("setALLMMode: the ALLM_Mode is not changed :%d\n", state); |
| return; |
| } |
| |
| bool isTVSupportDV = isTvSupportDV(); |
| |
| char ubootenv_amdv_enable[MESON_MODE_LEN] = {0}; |
| std::string cur_ColorAttribute; |
| char ubootenv_amdv_type[MESON_MODE_LEN] = {0}; |
| bool ret = false; |
| |
| switch (state) { |
| case -1: |
| [[fallthrough]]; |
| case 0: |
| //1. disable allm |
| sysfs_set_string(AUTO_LOW_LATENCY_MODE, ALLM_MODE[0]); |
| MESON_LOGI("setALLMMode: ALLM_Mode: %s", ALLM_MODE[0]); |
| //2.1 get dv status before enable allm |
| getBootEnv(UBOOTENV_DV_ENABLE, ubootenv_amdv_enable); |
| //2.2 get current hdmi output resolution |
| getDisplayMode(mCurrentMode); |
| //2.3 get current hdmi output color space |
| getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute); |
| //2.4 get dv type before enable allm |
| ret = getBootEnv(UBOOTENV_USER_DV_TYPE, ubootenv_amdv_type); |
| //3 enable dv |
| //when TV and current resolution support dv and dv is enable before enable allm |
| if (isTVSupportDV |
| && !strcmp(ubootenv_amdv_enable, "1") |
| && !(meson_mode_support_mode(mModeConType, MESON_DOLBY_VISION_PRIORITY, mCurrentMode))) { |
| // restore doblyvision when set -1/0 to ALLM |
| if (!ret) { |
| //best dv policy:sink-led -->source led |
| if (strstr(mConData.hdr_info.dv_deepcolor, "DV_RGB_444_8BIT") != NULL |
| && strstr(cur_ColorAttribute.c_str(), "444,8bit") != NULL) { |
| enableDV(AMDV_SET_ENABLE); |
| mSceneOutInfo.amdv_type = AMDV_SET_ENABLE; |
| } else if (strstr(mConData.hdr_info.dv_deepcolor, "LL_YCbCr_422_12BIT") != NULL |
| && strstr(cur_ColorAttribute.c_str(), "422,12bit") != NULL) { |
| enableDV(AMDV_SET_ENABLE_LL_YUV); |
| mSceneOutInfo.amdv_type = AMDV_SET_ENABLE_LL_YUV; |
| } else { |
| SYS_LOGI("can't enable dv for dv_deepcolor: %s and curColorAttribute: %s\n", |
| mConData.hdr_info.dv_deepcolor, cur_ColorAttribute.c_str()); |
| } |
| } else if (!strcmp(ubootenv_amdv_type, "2") && strstr(cur_ColorAttribute.c_str(), "422,12bit") != NULL) { |
| enableDV(AMDV_SET_ENABLE_LL_YUV); |
| mSceneOutInfo.amdv_type = AMDV_SET_ENABLE_LL_YUV; |
| } else if (!strcmp(ubootenv_amdv_type, "1") && strstr(cur_ColorAttribute.c_str(), "444,8bit") != NULL) { |
| enableDV(AMDV_SET_ENABLE); |
| mSceneOutInfo.amdv_type = AMDV_SET_ENABLE; |
| } else { |
| SYS_LOGI("can't enable dv for curColorAttribute: %s\n", cur_ColorAttribute.c_str()); |
| } |
| } |
| break; |
| case 1: |
| //when TV support dv and dv is enable |
| if (isTVSupportDV && isDVEnable()) { |
| mSceneOutInfo.amdv_type = AMDV_SET_DISABLE; |
| // disable the doblyvision when ALLM enable |
| disableDV(AMDV_SET_DISABLE); |
| } |
| //2. enable allm |
| sysfs_set_string(AUTO_LOW_LATENCY_MODE, ALLM_MODE[2]); |
| MESON_LOGI("setALLMMode: ALLM_Mode: %s", ALLM_MODE[2]); |
| break; |
| default: |
| MESON_LOGE("setALLMMode: ALLM_Mode: error state[%d]", state); |
| break; |
| } |
| } |
| |
| bool ModePolicy::isTvConnector() { |
| auto type = mConnector->connector_type; |
| if (type == DRM_MODE_CONNECTOR_MESON_LVDS_A || type == DRM_MODE_CONNECTOR_MESON_LVDS_B || |
| type == DRM_MODE_CONNECTOR_MESON_LVDS_C || type == DRM_MODE_CONNECTOR_MESON_VBYONE_A || |
| type == DRM_MODE_CONNECTOR_MESON_VBYONE_B || type == DRM_MODE_CONNECTOR_LVDS || |
| type == LEGACY_NON_DRM_CONNECTOR_PANEL) |
| return true; |
| |
| return false; |
| } |
| |
| int32_t ModePolicy::setAutoLowLatencyMode(bool enabled) { |
| auto type = mConnector->connector_type; |
| if (type == DRM_MODE_CONNECTOR_HDMIA) { |
| if (!isTvSupportALLM()) { |
| return -1; |
| } |
| |
| if (enabled) { |
| sysfs_set_string(LOW_LATENCY, LOW_LATENCY_ENABLE); |
| } else { |
| sysfs_set_string(LOW_LATENCY, LOW_LATENCY_DISABLE); |
| } |
| setALLMMode(enabled); |
| return 0; |
| } |
| |
| // do nothing for tv |
| if (isTvConnector()) |
| return 0; |
| |
| return -1; |
| } |
| |
| void ModePolicy::setAllowedHdrTypes(uint32_t allowedHdrTypes, bool isAuto, bool passThrough) { |
| //Match content Dynamic range |
| if (passThrough) { |
| setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_MATCH_CONTENT]); |
| } |
| // force SDR when autoAllowedHdrTypes are empty on system-preferred conversion |
| else if (allowedHdrTypes == 0 && isAuto) { |
| uint32_t userHdrType = 0; |
| userHdrType = userHdrType | (1 << HAL_HDR_AMDV); |
| userHdrType = userHdrType | (1 << HAL_HDR_HDR10); |
| userHdrType = userHdrType | (1 << HAL_HDR_HLG); |
| userHdrType = userHdrType | (1 << DRM_INVALID); |
| string keyValue = std::to_string(userHdrType); |
| setBootEnv(UBOOTENV_USER_PREFERRED_HDR_TYPE, keyValue.c_str()); |
| setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_SYSTEM_PREFERRED]); |
| return; |
| } else { |
| //bit0-bit4 for hdr type and 1 is disable 0 is enable |
| uint32_t userHdrType = 0; |
| userHdrType = userHdrType | (1 << HAL_HDR_AMDV); |
| userHdrType = userHdrType | (1 << HAL_HDR_HDR10); |
| userHdrType = userHdrType | (1 << HAL_HDR_HLG); |
| userHdrType = userHdrType | (1 << DRM_INVALID); |
| allowedHdrTypes ^= userHdrType; |
| allowedHdrTypes &= userHdrType; |
| string keyValue = std::to_string(allowedHdrTypes); |
| setBootEnv(UBOOTENV_USER_PREFERRED_HDR_TYPE, keyValue.c_str()); |
| if (isAuto) |
| setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_SYSTEM_PREFERRED]); |
| else |
| setBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, MESON_HDR_PREFERRED_POLICY[MESON_HDR_FORCE]); |
| |
| MESON_LOGD("%s AllowedHdrType %d isAuto %d keyValue %s \n", __func__, allowedHdrTypes, isAuto, keyValue.c_str()); |
| } |
| |
| return; |
| } |
| |
| int32_t ModePolicy::getPreferredHdrConversionType(void) { |
| int32_t outHdrConversionType = -1; |
| |
| char auto_policy[MESON_MODE_LEN] = {0}; |
| memset(auto_policy, 0, MESON_MODE_LEN); |
| getBootEnv(UBOOTENV_HDR_PREFERRED_POLICY, auto_policy); |
| |
| //Match content Dynamic range |
| if (strstr(auto_policy, MESON_HDR_PREFERRED_POLICY[MESON_HDR_MATCH_CONTENT])) { |
| mHdr_policy = MESON_HDR_POLICY_SOURCE; |
| mHdr_priority = MESON_G_DV_HDR10_HLG; |
| } |
| //System-preferred conversion or Force conversion |
| else { |
| bool isAuto = true; |
| if (strstr(auto_policy, MESON_HDR_PREFERRED_POLICY[MESON_HDR_FORCE])) { |
| isAuto = false; |
| } |
| |
| char user_hdr_type[MESON_MODE_LEN] = {0}; |
| memset(user_hdr_type, 0, MESON_MODE_LEN); |
| bool ret = getBootEnv(UBOOTENV_USER_PREFERRED_HDR_TYPE, user_hdr_type); |
| int32_t allowedHdrType = atoi(user_hdr_type); |
| if (ret) { |
| allowedHdrType = atoi(user_hdr_type); |
| } else { |
| allowedHdrType = 0; //all hdr enable as default |
| } |
| |
| //force SDR when autoAllowedHdrTypes are empty on system-preferred conversion |
| uint32_t userHdrType = 0; |
| userHdrType = userHdrType | (1 << HAL_HDR_AMDV); |
| userHdrType = userHdrType | (1 << HAL_HDR_HDR10); |
| userHdrType = userHdrType | (1 << HAL_HDR_HLG); |
| userHdrType = userHdrType | (1 << DRM_INVALID); |
| string keyValue = std::to_string(userHdrType); |
| if (isAuto && strstr (user_hdr_type, keyValue.c_str())) { |
| mHdr_priority = MESON_G_SDR; |
| outHdrConversionType = DRM_INVALID; |
| } else { |
| bool containDVType = false, containHDR10Type = false, |
| containHLGType = false, containSDRType = false; |
| |
| MESON_LOGD("allowedHdrType 0x%x ", allowedHdrType); |
| if (!(allowedHdrType & (1 << HAL_HDR_AMDV))) |
| containDVType = true; |
| if (!(allowedHdrType & (1 << HAL_HDR_HDR10))) |
| containHDR10Type = true; |
| if (!(allowedHdrType & (1 << HAL_HDR_HLG))) |
| containHLGType = true; |
| if (!(allowedHdrType & (1 << DRM_INVALID))) |
| containSDRType = true; |
| |
| drm_hdr_capabilities hdrCaps; |
| getHdrCapabilities(&hdrCaps); |
| |
| if (isAuto) { |
| if (hdrCaps.DVSupported) { |
| if (containHLGType && containHDR10Type && containDVType) { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_DV_HDR10_HLG; |
| outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV); |
| } else if (containHDR10Type && containDVType) { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_DV_HDR10; |
| outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV); |
| } else if (containHLGType && containDVType) { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_DV_HLG; |
| outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV); |
| } else if (containHLGType && containHDR10Type) { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_HDR10_HLG; |
| outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10); |
| } else if (containDVType) { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_DV; |
| outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV); |
| } else if (containHDR10Type) { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_HDR10; |
| outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10); |
| } else if (containHLGType) { |
| mHdr_priority = MESON_G_HLG; |
| mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source due to dv can't HLG output |
| } else { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_SDR; |
| outHdrConversionType = DRM_INVALID; //force sdr |
| } |
| } else { |
| if (containHLGType && containHDR10Type) { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_HDR10_HLG; |
| outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10); |
| } else if (containHDR10Type) { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_HDR10; |
| outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10); |
| } else if (containHLGType) { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_HLG; |
| outHdrConversionType = static_cast<int32_t>(HAL_HDR_HLG); |
| } else { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_SDR; |
| outHdrConversionType = DRM_INVALID; //force sdr |
| } |
| } |
| } else { |
| if (containDVType) { |
| if (hdrCaps.DVSupported) { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_DV; |
| outHdrConversionType = static_cast<int32_t>(HAL_HDR_AMDV); |
| } else { |
| mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source |
| mHdr_priority = MESON_G_DV_HDR10_HLG; |
| } |
| } else if (containHDR10Type) { |
| if (hdrCaps.HDR10Supported) { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_HDR10; |
| outHdrConversionType = static_cast<int32_t>(HAL_HDR_HDR10); |
| } else { |
| mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source |
| mHdr_priority = MESON_G_DV_HDR10_HLG; |
| } |
| } else if (containHLGType) { |
| if (hdrCaps.HLGSupported) { |
| if (hdrCaps.DVSupported) { |
| mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source due to dv can't HLG output |
| mHdr_priority = MESON_G_DV_HDR10_HLG; |
| } else { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_HLG; |
| outHdrConversionType = static_cast<int32_t>(HAL_HDR_HLG); |
| } |
| } else { |
| mHdr_policy = MESON_HDR_POLICY_SOURCE; //follow source |
| mHdr_priority = MESON_G_DV_HDR10_HLG; |
| } |
| } else { |
| mHdr_policy = MESON_HDR_POLICY_SINK; |
| mHdr_priority = MESON_G_SDR; |
| outHdrConversionType = DRM_INVALID; //force sdr |
| } |
| } |
| } |
| } |
| |
| MESON_LOGD("hdr_policy:%d hdr_priority:0x%x outHdrConversionType:%d ", mHdr_policy, mHdr_priority, outHdrConversionType); |
| return outHdrConversionType; |
| } |
| |
| int32_t ModePolicy::setHdrConversionPolicy(bool passthrough, int32_t forceType) { |
| int32_t ret = 0; |
| MESON_LOGD("%s passthrough %d forceType %d", |
| __func__, passthrough, forceType); |
| |
| if (passthrough || (forceType == -1)) { |
| setBootEnv(UBOOTENV_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]); |
| |
| char hdr_priority[MESON_MODE_LEN] = {0}; |
| sprintf(hdr_priority, "%d", mHdr_priority); |
| setBootEnv(UBOOTENV_HDR_PRIORITY, hdr_priority); |
| // set current hdmi mode |
| getDisplayMode(mCurrentMode); |
| setSourceOutputMode(mCurrentMode); |
| } else { |
| std::string type = FORCE_AMDV; |
| meson_hdr_priority_e priority = MESON_DOLBY_VISION_PRIORITY; |
| switch (forceType) { |
| case DRM_AMDV: { |
| priority = MESON_DOLBY_VISION_PRIORITY; |
| type = FORCE_AMDV; |
| break; |
| } |
| case DRM_HDR10:{ |
| priority = MESON_HDR10_PRIORITY; |
| type = FORCE_HDR10; |
| break; |
| } |
| case DRM_HLG:{ |
| priority = MESON_HDR10_PRIORITY; |
| type = FORCE_HLG; |
| break; |
| } |
| case DRM_INVALID: { |
| priority = MESON_SDR_PRIORITY; |
| type = AMDV_DISABLE_FORCE_SDR; |
| break; |
| } |
| default: |
| MESON_LOGE("setHdrConversionStrategy: error type[%d]", forceType); |
| ret = -1; |
| break; |
| } |
| |
| if (!ret) { |
| getDisplayMode(mCurrentMode); |
| meson_mode_set_policy_input(mModeConType, &mConData); |
| if (!meson_mode_support_mode(mModeConType, priority, mCurrentMode)) { |
| char hdr_policy[MESON_MODE_LEN] = {0}; |
| sprintf(hdr_policy, "%d", mHdr_policy); |
| setBootEnv(UBOOTENV_HDR_POLICY, hdr_policy); |
| |
| char hdr_priority[MESON_MODE_LEN] = {0}; |
| sprintf(hdr_priority, "%d", mHdr_priority); |
| setBootEnv(UBOOTENV_HDR_PRIORITY, hdr_priority); |
| |
| setSourceOutputMode(mCurrentMode); |
| } else { |
| MESON_LOGW("%s mode check failed\n", __func__); |
| ret = -EINVAL; |
| } |
| } |
| } |
| |
| return ret; |
| } |
| |
| /* |
| * apply setting |
| */ |
| void ModePolicy::applyDisplaySetting(bool force) { |
| //quiescent boot need not output |
| bool quiescent = sys_get_bool_prop("ro_boot_quiescent", false); |
| |
| MESON_LOGI("quiescent_mode is %d\n", quiescent); |
| if (quiescent && (mState == OUTPUT_MODE_STATE_INIT)) { |
| MESON_LOGI("don't need to setting hdmi when quiescent mode\n"); |
| return; |
| } |
| |
| //check cvbs mode |
| bool cvbsMode = false; |
| |
| if (!strcmp(mSceneOutInfo.displaymode, MODE_480CVBS) || !strcmp(mSceneOutInfo.displaymode, MODE_576CVBS) |
| || !strcmp(mSceneOutInfo.displaymode, MODE_PAL_M) || !strcmp(mSceneOutInfo.displaymode, MODE_PAL_N) |
| || !strcmp(mSceneOutInfo.displaymode, MODE_NTSC_M) |
| || !strcmp(mSceneOutInfo.displaymode, "null") || !strcmp(mSceneOutInfo.displaymode, "dummy_l") |
| || !strcmp(mSceneOutInfo.displaymode, MODE_PANEL)) { |
| cvbsMode = true; |
| } |
| |
| /* not enable phy in systemcontrol by default |
| * as phy will be enabled in driver when set mode |
| * only enable phy if phy is disabled but not enabled |
| */ |
| bool phy_enabled_already = true; |
| |
| // 1. update hdmi frac_rate_policy |
| char frac_rate_policy[MESON_MODE_LEN] = {0}; |
| char cur_frac_rate_policy[MESON_MODE_LEN] = {0}; |
| bool frac_rate_policy_change = false; |
| std::string policy; |
| |
| if (mReason != OUTPUT_CHANGE_BY_HWC) { |
| getDisplayAttribute(DISPLAY_FRAC_RATE_POLICY, policy); |
| strcpy(cur_frac_rate_policy, policy.c_str()); |
| getBootEnv(UBOOTENV_FRAC_RATE_POLICY, frac_rate_policy); |
| if (strstr(frac_rate_policy, cur_frac_rate_policy) == NULL) { |
| setDisplayAttribute(DISPLAY_FRAC_RATE_POLICY, frac_rate_policy); |
| frac_rate_policy_change = true; |
| } else { |
| MESON_LOGI("cur frac_rate_policy is equals\n"); |
| } |
| } else { |
| getDisplayAttribute(DISPLAY_FRAC_RATE_POLICY, policy); |
| strcpy(cur_frac_rate_policy, policy.c_str()); |
| char defVal[] = "2"; |
| sys_get_string_prop_default(HDMI_FRC_POLICY_PROP,frac_rate_policy, defVal); |
| if (strstr(frac_rate_policy,"2")) { |
| getBootEnv(UBOOTENV_FRAC_RATE_POLICY, frac_rate_policy); |
| } |
| MESON_LOGI("get frc policy from hwc is %s and current value is %s\n",frac_rate_policy, cur_frac_rate_policy); |
| if (strstr(frac_rate_policy, cur_frac_rate_policy) == NULL) { |
| frac_rate_policy_change = true; |
| } |
| } |
| |
| // 2. set hdmi final color space |
| char curColorAttribute[MESON_MODE_LEN] = {0}; |
| char final_deepcolor[MESON_MODE_LEN] = {0}; |
| bool attr_change = false; |
| |
| std::string cur_ColorAttribute; |
| getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute); |
| strcpy(curColorAttribute, cur_ColorAttribute.c_str()); |
| strcpy(final_deepcolor, mSceneOutInfo.deepcolor); |
| MESON_LOGI("curDeepcolor[%s] final_deepcolor[%s]\n", curColorAttribute, final_deepcolor); |
| |
| if (strstr(curColorAttribute, final_deepcolor) == NULL) { |
| MESON_LOGI("set color space from:%s to %s\n", curColorAttribute, final_deepcolor); |
| // setDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, final_deepcolor); |
| cur_ColorAttribute = final_deepcolor; |
| attr_change = true; |
| } else { |
| MESON_LOGI("cur deepcolor is equals\n"); |
| } |
| |
| // 3. update hdr strategy |
| bool hdr_policy_change = false; |
| std::string cur_hdr_policy; |
| getDisplayAttribute(DISPLAY_HDR_POLICY, cur_hdr_policy); |
| MESON_LOGI("cur hdr policy:%s\n", cur_hdr_policy.c_str()); |
| |
| std::string cur_hdr_force_mode; |
| getDisplayAttribute(DISPLAY_FORCE_HDR_MODE, cur_hdr_force_mode); |
| MESON_LOGI("cur hdr force mode:%s\n", cur_hdr_force_mode.c_str()); |
| |
| std::string cur_amdv_mode; |
| getDisplayAttribute(DISPLAY_AMDV_MODE, cur_amdv_mode); |
| MESON_LOGI("cur dv mode:%s\n", cur_amdv_mode.c_str()); |
| |
| std::string cur_amdv_policy; |
| getDisplayAttribute(DISPLAY_AMDV_POLICY, cur_amdv_policy); |
| MESON_LOGI("cur dv policy:%s\n", cur_amdv_policy.c_str()); |
| |
| char hdr_force_mode[MESON_MODE_LEN] = {0}; |
| gethdrforcemode(hdr_force_mode); |
| |
| char hdr_policy[MESON_MODE_LEN] = {0}; |
| getHdrStrategy(hdr_policy); |
| |
| if (!isDVEnable()) { |
| if (strstr(cur_hdr_policy.c_str(), hdr_policy) == NULL) { |
| MESON_LOGI("set hdr policy from:%s to %s\n", cur_hdr_policy.c_str(), hdr_policy); |
| hdr_policy_change = true; |
| } else if (!strcmp(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]) && (strstr(cur_hdr_force_mode.c_str(), hdr_force_mode) == NULL)) { |
| MESON_LOGI("set hdr force mode from:%s to %s\n", cur_hdr_force_mode.c_str(), hdr_force_mode); |
| hdr_policy_change = true; |
| } |
| } else { |
| if (strstr(cur_amdv_policy.c_str(), hdr_policy) == NULL) { |
| MESON_LOGI("set dv policy from:%s to %s\n", cur_amdv_policy.c_str(), hdr_policy); |
| hdr_policy_change = true; |
| } else if ((mSceneOutInfo.amdv_type != AMDV_SET_DISABLE) |
| && (!strcmp(hdr_policy, AMDV_POLICY_FORCE_MODE) |
| && (strstr(cur_amdv_mode.c_str(), hdr_force_mode) == NULL))) { |
| MESON_LOGI("set dv force mode from:%s to %s\n", cur_amdv_mode.c_str(), hdr_force_mode); |
| hdr_policy_change = true; |
| } |
| } |
| |
| //update hdr priority |
| bool hdr_priority_change = false; |
| meson_hdr_priority_e cur_hdr_priority; |
| cur_hdr_priority = (meson_hdr_priority_e)getCurrentHdrPriority(); |
| |
| meson_hdr_priority_e hdr_priority; |
| hdr_priority = (meson_hdr_priority_e)getHdrPriority(); |
| |
| if (cur_hdr_priority != hdr_priority) { |
| SYS_LOGI("set hdr priority from:%x to %x\n", cur_hdr_priority, hdr_priority); |
| hdr_priority_change = true; |
| } |
| |
| // 4. check dv |
| int amdv_type = AMDV_SET_DISABLE; |
| bool amdv_change = false; |
| |
| amdv_type = mSceneOutInfo.amdv_type; |
| amdv_change = checkDVStatusChanged(amdv_type); |
| if (isMboxSupportDV() && amdv_change) { |
| //4.1 set avmute when signal change at boot |
| if ((OUTPUT_MODE_STATE_INIT == mState) |
| && (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]))) { |
| // setDisplayAttribute(DISPLAY_HDMI_AVMUTE, "1"); |
| } |
| //4.2 set dummy_l mode when dv change at UI switch |
| if ((OUTPUT_MODE_STATE_SWITCH == mState) && amdv_change) { |
| setDisplayMode("dummy_l"); |
| } |
| //4.3 enable or disable dv core |
| if (AMDV_SET_DISABLE != amdv_type) { |
| enableDV(amdv_type); |
| } else { |
| disableDV(amdv_type); |
| } |
| |
| MESON_LOGI("isDVEnable: %d", isDVEnable()); |
| } else { |
| amdv_change = false; |
| MESON_LOGI("cur DvMode is equals\n"); |
| } |
| |
| // 5. check hdmi output mode |
| char final_displaymode[MESON_MODE_LEN] = {0}; |
| char curDisplayMode[MESON_MODE_LEN] = {0}; |
| bool modeChange = false; |
| |
| getDisplayMode(curDisplayMode); |
| strcpy(final_displaymode, mSceneOutInfo.displaymode); |
| MESON_LOGI("curMode:[%s] ,final_displaymode[%s]\n", curDisplayMode, final_displaymode); |
| |
| if (!isMatchMode(curDisplayMode, final_displaymode)) { |
| modeChange = true; |
| } else { |
| MESON_LOGI("cur mode is equals\n"); |
| } |
| |
| //6. check any change |
| bool isNeedChange = false; |
| |
| if (amdv_change || modeChange || attr_change || frac_rate_policy_change || hdr_policy_change || hdr_priority_change) { |
| isNeedChange = true; |
| } else if (force) { |
| isNeedChange = true; |
| MESON_LOGD("force changed"); |
| } else { |
| MESON_LOGI("nothing need to be changed\n"); |
| } |
| |
| // 8. set hdmi final output mode |
| if (isNeedChange) { |
| //apply hdr policy to driver sysfs |
| if (hdr_policy_change) { |
| if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) { |
| setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]); |
| if (isDVEnable()) { |
| setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]); |
| } |
| } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) { |
| setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]); |
| if (isDVEnable()) { |
| setDisplayAttribute(DISPLAY_AMDV_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]); |
| } |
| } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]) || strstr(hdr_policy, AMDV_POLICY_FORCE_MODE)) { |
| char hdr_force_mode[MESON_MODE_LEN] = {0}; |
| gethdrforcemode(hdr_force_mode); |
| setDisplayAttribute(DISPLAY_FORCE_HDR_MODE, hdr_force_mode); |
| setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]); |
| if (isDVEnable()) { |
| setDisplayAttribute(DISPLAY_AMDV_POLICY, AMDV_POLICY_FORCE_MODE); |
| if (strstr(hdr_force_mode, FORCE_AMDV)) { |
| setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_AMDV); |
| } else if (strstr(hdr_force_mode, FORCE_HDR10)) { |
| setDisplayAttribute(DISPLAY_AMDV_MODE, FORCE_HDR10); |
| } else if (strstr(hdr_force_mode, AMDV_DISABLE_FORCE_SDR)) { |
| // 8bit or not |
| // std::string cur_ColorAttribute; |
| // getDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, cur_ColorAttribute); |
| if (cur_ColorAttribute.find("8bit", 0) != std::string::npos) { |
| setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_8BIT); |
| } else { |
| setDisplayAttribute(DISPLAY_AMDV_MODE, AMDV_ENABLE_FORCE_SDR_10BIT); |
| } |
| } |
| } |
| } |
| } |
| |
| if (attr_change || modeChange || frac_rate_policy_change || force) |
| mAdapter->setColorAttribute(final_deepcolor); |
| |
| //apply hdr priority to driver sysfs |
| if (hdr_priority_change) { |
| char tmp[MESON_MODE_LEN] = {0}; |
| sprintf(tmp, "%d", hdr_priority); |
| setDisplayAttribute(DISPLAY_HDR_PRIORITY, tmp); |
| } |
| |
| //set hdmi mode |
| setDisplayMode(final_displaymode); |
| setQMSVRR( curDisplayMode, final_displaymode ); |
| |
| /* phy already turned on after write display/mode node */ |
| phy_enabled_already = true; |
| } else { |
| MESON_LOGI("curDisplayMode is equal final_displaymode, Do not need set it\n"); |
| } |
| |
| // graphic |
| char final_Mode[MESON_MODE_LEN] = {0}; |
| getDisplayMode(final_Mode); |
| char defVal[] = "0x0"; |
| if (sys_get_bool_prop(PROP_DISPLAY_SIZE_CHECK, true)) { |
| char resolution[MESON_MODE_LEN] = {0}; |
| char defaultResolution[MESON_MODE_LEN] = {0}; |
| char finalResolution[MESON_MODE_LEN] = {0}; |
| int w = 0, h = 0, w1 =0, h1 = 0; |
| sysfs_get_string(SYS_DISPLAY_RESOLUTION, resolution, MESON_MODE_LEN); |
| sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal); |
| sscanf(resolution, "%dx%d", &w, &h); |
| sscanf(defaultResolution, "%dx%d", &w1, &h1); |
| if ((w != w1) || (h != h1)) { |
| if (strstr(final_displaymode, "null") && w1 != 0) { |
| sprintf(finalResolution, "%dx%d", w1, h1); |
| } else { |
| sprintf(finalResolution, "%dx%d", w, h); |
| } |
| sys_set_prop(PROP_DISPLAY_SIZE, finalResolution); |
| } |
| } |
| sys_set_prop(PROP_DISPLAY_ALLM, isTvSupportALLM() ? "1" : "0"); |
| sys_set_prop(PROP_DISPLAY_GAME, getGameContentTypeSupport() ? "1" : "0"); |
| |
| char defaultResolution[MESON_MODE_LEN] = {0}; |
| sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal); |
| MESON_LOGI("set display-size:%s\n", defaultResolution); |
| |
| int position[4] = { 0, 0, 0, 0 };//x,y,w,h |
| getPosition(final_displaymode, position); |
| setPosition(final_displaymode, position[0], position[1],position[2], position[3]); |
| |
| //audio |
| char value[MESON_MAX_STR_LEN] = {0}; |
| memset(value, 0, sizeof(0)); |
| getBootEnv(UBOOTENV_DIGITAUDIO, value); |
| setDigitalMode(value); |
| } |
| |
| void ModePolicy::getFramebufferSize(int disp, uint32_t & width, uint32_t & height) { |
| char uiMode[PROPERTY_VALUE_MAX] = {0}; |
| if (disp == 0) { |
| /*primary display*/ |
| if (sys_get_string_prop_default("persist_vendor_hwc_ui_mode", uiMode, "1080") > 0) { |
| if (!strncmp(uiMode, "720", 3)) { |
| width = 1280; |
| height = 720; |
| } else if (!strncmp(uiMode, "1080", 4)) { |
| width = 1920; |
| height = 1080; |
| } else { |
| MESON_ASSERT(0, "%s: get not support mode [%s] from vendor.ui_mode", |
| __func__, uiMode); |
| } |
| } else { |
| width = 1920; |
| height = 1080; |
| } |
| } |
| } |
| |
| int32_t ModePolicy::initialize() { |
| uint32_t width = 1280; |
| uint32_t height = 1080; |
| char log_level[PROPERTY_VALUE_MAX] = { 0 }; |
| |
| sys_get_string_prop_default("WESTON_GL_MODE_POLICY_DEBUG", log_level, "2"); |
| g_activeLevel = atoi(log_level); |
| mAdapter->setLogLevel(g_activeLevel); |
| |
| bootenv_init(); |
| getFramebufferSize(mDisplayId, width, height); |
| mDefaultUI = to_string(height); |
| |
| mAdapter->initDisplayAttributeInfo(mCrtc, mConnector); |
| updateHdrCaps(); |
| if (DISPLAY_TYPE_MBOX == mDisplayType) { |
| // mTxAuth = std::make_shared<HDCPTxAuth>(); |
| |
| setSourceDisplay(OUTPUT_MODE_STATE_INIT); |
| applyDisplaySetting(false); |
| } else if (DISPLAY_TYPE_TV == mDisplayType) { |
| setSinkDisplay(true); |
| } |
| #if 0 |
| } else if (DISPLAY_TYPE_TABLET == mDisplayType) { |
| |
| } else if (DISPLAY_TYPE_REPEATER == mDisplayType) { |
| setSourceDisplay(OUTPUT_MODE_STATE_INIT); |
| } |
| #endif |
| |
| return 0; |
| } |
| |
| void ModePolicy::setSinkDisplay(bool initState) { |
| char current_mode[MESON_MODE_LEN] = {0}; |
| char outputmode[MESON_MODE_LEN] = {0}; |
| |
| getDisplayMode(current_mode); |
| getBootEnv(UBOOTENV_OUTPUTMODE, outputmode); |
| MESON_LOGD("init tv display old outputmode:%s, outputmode:%s\n", current_mode, outputmode); |
| |
| if (strlen(outputmode) == 0) |
| strncpy(outputmode, mDefaultUI.c_str(), MESON_MODE_LEN-1); |
| |
| setSinkOutputMode(outputmode, initState); |
| } |
| |
| void ModePolicy::setSinkOutputMode(const char* outputmode, bool initState) { |
| [[maybe_unused]] bool sinkInitState = initState; |
| MESON_LOGI("set sink output mode:%s, init state:%d\n", outputmode, sinkInitState); |
| |
| //set output mode |
| char curMode[MESON_MODE_LEN] = {0}; |
| getDisplayMode(curMode); |
| |
| MESON_LOGI("curMode = %s outputmode = %s", curMode, outputmode); |
| if (strstr(curMode, outputmode) == NULL) { |
| setDisplayMode(outputmode); |
| } |
| |
| char defVal[PROPERTY_VALUE_MAX] = "0x0"; |
| if (sys_get_bool_prop(PROP_DISPLAY_SIZE_CHECK, true)) { |
| char resolution[MESON_MODE_LEN] = {0}; |
| char defaultResolution[MESON_MODE_LEN] = {0}; |
| char finalResolution[MESON_MODE_LEN] = {0}; |
| int w = 0, h = 0, w1 =0, h1 = 0; |
| sysfs_get_string(SYS_DISPLAY_RESOLUTION, resolution, MESON_MODE_LEN); |
| |
| sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal); |
| sscanf(resolution, "%dx%d", &w, &h); |
| sscanf(defaultResolution, "%dx%d", &w1, &h1); |
| if ((w != w1) || (h != h1)) { |
| if (strstr(outputmode, "null") && w1 != 0) { |
| sprintf(finalResolution, "%dx%d", w1, h1); |
| } else { |
| sprintf(finalResolution, "%dx%d", w, h); |
| } |
| sys_set_prop(PROP_AMDV_PRIORITY, finalResolution); |
| } |
| } |
| |
| char defaultResolution[MESON_MODE_LEN] = {0}; |
| sys_get_string_prop_default(PROP_DISPLAY_SIZE, defaultResolution, defVal); |
| MESON_LOGI("set display-size:%s\n", defaultResolution); |
| |
| //update hwc windows size |
| int position[4] = { 0, 0, 0, 0 };//x,y,w,h |
| getPosition(outputmode, position); |
| setPosition(outputmode, position[0], position[1],position[2], position[3]); |
| |
| //update hdr policy |
| if ((isMboxSupportDV() == false)) { |
| if (sys_get_bool_prop(PROP_AMDV_FEATURE, false)) { |
| char hdr_policy[MESON_MODE_LEN] = {0}; |
| getHdrStrategy(hdr_policy); |
| if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK])) { |
| setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SINK]); |
| } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE])) { |
| setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_SOURCE]); |
| } else if (strstr(hdr_policy, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE])) { |
| setDisplayAttribute(DISPLAY_HDR_POLICY, MESON_HDR_POLICY[MESON_HDR_POLICY_FORCE]); |
| } |
| } else { |
| initHdrSdrMode(); |
| } |
| } |
| |
| if (isMboxSupportDV()) { |
| if (isTvDVEnable()) { |
| setTvDVEnable(); |
| } else { |
| setTvDVDisable(); |
| } |
| } |
| |
| //audio |
| char value[MESON_MAX_STR_LEN] = {0}; |
| memset(value, 0, sizeof(0)); |
| getBootEnv(UBOOTENV_DIGITAUDIO, value); |
| setDigitalMode(value); |
| |
| //save output mode |
| char finalMode[MESON_MODE_LEN] = {0}; |
| getDisplayMode(finalMode); |
| if (DISPLAY_TYPE_TABLET != mDisplayType) { |
| setBootEnv(UBOOTENV_OUTPUTMODE, (char *)finalMode); |
| } |
| if (strstr(finalMode, "cvbs") != NULL) { |
| setBootEnv(UBOOTENV_CVBSMODE, (char *)finalMode); |
| } else if (strstr(finalMode, "hz") != NULL) { |
| setBootEnv(UBOOTENV_HDMIMODE, (char *)finalMode); |
| } |
| |
| MESON_LOGI("set output mode:%s done\n", finalMode); |
| } |
| |
| bool ModePolicy::isHdmiUsed() { |
| bool ret = true; |
| char hdmi_state[MESON_MODE_LEN] = {0}; |
| |
| sysfs_get_string(DISPLAY_HDMI_USED, hdmi_state, MESON_MODE_LEN); |
| |
| if (strstr(hdmi_state, "1") == NULL) { |
| ret = false; |
| } |
| |
| return ret; |
| } |
| |
| bool ModePolicy::isConnected() { |
| bool ret = ((mConnectorType == CONN_TYPE_HDMI) && |
| (mConnector->connection == DRM_MODE_CONNECTED)); |
| return ret; |
| } |
| |
| bool ModePolicy::isVMXCertification() { |
| return sys_get_bool_prop(PROP_VMX, false); |
| } |
| |
| bool ModePolicy::isHdmiEdidParseOK() { |
| bool ret = true; |
| |
| char edidParsing[MESON_MODE_LEN] = {0}; |
| sysfs_get_string(DISPLAY_EDID_STATUS, edidParsing, MESON_MODE_LEN); |
| |
| if (strcmp(edidParsing, "ok")) { |
| ret = false; |
| } |
| |
| return ret; |
| } |
| |
| bool ModePolicy::isBestPolicy() { |
| char isBestMode[MESON_MODE_LEN] = {0}; |
| if (DISPLAY_TYPE_TV == mDisplayType) { |
| return false; |
| } |
| |
| return !getBootEnv(UBOOTENV_ISBESTMODE, isBestMode) || strcmp(isBestMode, "true") == 0; |
| } |
| |
| bool ModePolicy::isBestColorSpace() { |
| bool ret = false; |
| char user_colorattr[MESON_MODE_LEN] = {0}; |
| if (DISPLAY_TYPE_TV == mDisplayType) { |
| return false; |
| } |
| |
| ret = getBootEnv(UBOOTENV_USER_COLORATTRIBUTE, user_colorattr); |
| |
| if (!ret) { |
| return true; |
| } else if (strstr(user_colorattr, "bit") == NULL) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| void ModePolicy::setDefaultMode() { |
| MESON_LOGE("EDID parsing error detected\n"); |
| |
| // check hdmi output mode |
| char curDisplayMode[MESON_MODE_LEN] = {0}; |
| getDisplayMode(curDisplayMode); |
| |
| if (!isMatchMode(curDisplayMode, MESON_DEFAULT_HDMI_MODE)) { |
| //set default color format |
| setDisplayAttribute(DISPLAY_HDMI_COLOR_ATTR, MESON_DEFAULT_COLOR_FORMAT); |
| //set default resolution |
| setDisplayMode(MESON_DEFAULT_HDMI_MODE); |
| |
| //update display position |
| int position[4] = { 0, 0, 0, 0 };//x,y,w,h |
| getPosition(MESON_DEFAULT_HDMI_MODE, position); |
| setPosition(MESON_DEFAULT_HDMI_MODE, position[0], position[1],position[2], position[3]); |
| } else { |
| MESON_LOGI("cur mode is default mode\n"); |
| } |
| } |
| |
| void ModePolicy::setDisplay(output_mode_state state) |
| { |
| if ((state == OUTPUT_MODE_STATE_INIT) || |
| (state == OUTPUT_MODE_STATE_POWER)) { |
| memset(&mConData, 0, sizeof(meson_policy_in)); |
| memset(&mDvInfo, 0, sizeof(hdmi_amdv_info_t)); |
| mState = state; |
| mConData.state = static_cast<meson_mode_state>(state); |
| |
| getConnectorData(&mConData, &mDvInfo); |
| if (isTvSupportDV() && isMboxSupportDV()) { |
| strcpy(mDvInfo.amdv_enable, "1"); |
| mConData.hdr_info.is_amdv_enable = isDVEnable(); |
| } |
| |
| strcpy(mConData.cur_displaymode, mConData.con_info.ubootenv_hdmimode); |
| } |
| |
| // TOD sceneProcess |
| if (isBestPolicy()) { |
| if (state == OUTPUT_MODE_STATE_INIT || mPolicy == MESON_POLICY_INVALID) { |
| mPolicy = MESON_POLICY_MIX; |
| } |
| } else { |
| mPolicy = MESON_POLICY_INVALID; |
| } |
| |
| meson_mode_set_policy(mModeConType, mPolicy); |
| meson_mode_set_policy_input(mModeConType, &mConData); |
| meson_mode_get_policy_output(mModeConType, &mSceneOutInfo); |
| |
| //5. apply settings to driver |
| applyDisplaySetting(state == OUTPUT_MODE_STATE_POWER); |
| } |
| /* |
| * OUTPUT_MODE_STATE_INIT for boot |
| * OUTPUT_MODE_STATE_POWER for hdmi plug and suspend/resume |
| */ |
| void ModePolicy::setSourceDisplay(output_mode_state state) { |
| std::lock_guard<std::mutex> lock(mMutex); |
| |
| //1. hdmi used and hpd = 0 |
| //set dummy_l mode |
| if ((isHdmiUsed() == true) && (isConnected() == false)) { |
| MESON_LOGD("hdmi usd, set cvbs"); |
| setDisplay(state); |
| MESON_LOGI("hdmi used but plugout when boot\n"); |
| return; |
| } |
| |
| //2. hdmi edid parse error and hpd = 1 |
| //set default reolsution and color format |
| if ((isHdmiEdidParseOK() == false) && |
| (isConnected() == true)) { |
| setDefaultMode(); |
| return; |
| } |
| |
| //3. update hdmi info when boot and hdmi plug/suspend/resume |
| if ((state == OUTPUT_MODE_STATE_INIT) || |
| (state == OUTPUT_MODE_STATE_POWER)) { |
| memset(&mConData, 0, sizeof(meson_policy_in)); |
| memset(&mDvInfo, 0, sizeof(hdmi_amdv_info_t)); |
| mState = state; |
| mConData.state = static_cast<meson_mode_state>(state); |
| |
| getConnectorData(&mConData, &mDvInfo); |
| if (isTvSupportDV() && isMboxSupportDV()) { |
| strcpy(mDvInfo.amdv_enable, "1"); |
| mConData.hdr_info.is_amdv_enable = isDVEnable(); |
| } |
| |
| strcpy(mConData.cur_displaymode, mConData.con_info.ubootenv_hdmimode); |
| } |
| |
| // TOD sceneProcess |
| if (isBestPolicy()) { |
| if (state == OUTPUT_MODE_STATE_INIT || mPolicy == MESON_POLICY_INVALID) { |
| mPolicy = MESON_POLICY_MIX; |
| } |
| } else { |
| mPolicy = MESON_POLICY_INVALID; |
| } |
| |
| meson_mode_set_policy(mModeConType, mPolicy); |
| meson_mode_set_policy_input(mModeConType, &mConData); |
| meson_mode_get_policy_output(mModeConType, &mSceneOutInfo); |
| |
| } |
| |
| void ModePolicy::setSourceOutputModeNoLock(const char* outputmode, bool force) { |
| if (DISPLAY_TYPE_TV == mDisplayType) { |
| setSinkOutputMode(outputmode, false); |
| } else { |
| |
| getConnectorUserData(&mConData, &mDvInfo); |
| |
| getHdrUserInfo(&mConData.hdr_info); |
| |
| mState = OUTPUT_MODE_STATE_SWITCH; |
| mConData.state = static_cast<meson_mode_state>(mState); |
| |
| strcpy(mConData.cur_displaymode, outputmode); |
| meson_mode_set_policy_input(mModeConType, &mConData); |
| meson_mode_get_policy_output(mModeConType, &mSceneOutInfo); |
| |
| applyDisplaySetting(force); |
| } |
| } |
| |
| void ModePolicy::setSourceOutputMode(const char* outputmode, bool force) { |
| std::lock_guard<std::mutex> lock(mMutex); |
| |
| setSourceOutputModeNoLock(outputmode, force); |
| } |
| |
| void ModePolicy::getConnectorUserData(struct meson_policy_in* data, hdmi_amdv_info_t *dinfo) { |
| if (!data || !dinfo) { |
| MESON_LOGE("%s data is NULL\n", __FUNCTION__); |
| return; |
| } |
| |
| bool ret = false; |
| |
| //hdmi color space best policy flag |
| data->con_info.is_bestcolorspace = isBestColorSpace(); |
| |
| MESON_LOGI("isbestColorspace:%d\n", |
| data->con_info.is_bestcolorspace); |
| |
| getDisplayMode(mCurrentMode); |
| ret = getBootEnv(UBOOTENV_HDMIMODE, data->con_info.ubootenv_hdmimode); |
| if (!ret) { |
| //if env is null,use none as default value |
| strcpy(data->con_info.ubootenv_hdmimode, "none"); |
| } |
| getBootEnv(UBOOTENV_CVBSMODE, data->con_info.ubootenv_cvbsmode); |
| MESON_LOGI("hdmi_current_mode:%s, ubootenv hdmimode:%s cvbsmode:%s\n", |
| mCurrentMode, |
| data->con_info.ubootenv_hdmimode, |
| data->con_info.ubootenv_cvbsmode); |
| |
| ret = getBootEnv(UBOOTENV_USER_COLORATTRIBUTE, data->con_info.ubootenv_colorattr); |
| if (!ret) { |
| //if env is null,use none as default value |
| strcpy(data->con_info.ubootenv_colorattr, "none"); |
| } |
| MESON_LOGI("ubootenv_colorattribute:%s\n", |
| data->con_info.ubootenv_colorattr); |
| |
| //if no dolby_status env set to std for enable dv |
| //if box support dv |
| char amdv_enable[MESON_MODE_LEN]; |
| ret = getBootEnv(UBOOTENV_DV_ENABLE, amdv_enable); |
| if (ret) { |
| strcpy(dinfo->amdv_enable, amdv_enable); |
| } else if (isMboxSupportDV()) { |
| strcpy(dinfo->amdv_enable, "1"); |
| } else { |
| strcpy(dinfo->amdv_enable, "0"); |
| } |
| MESON_LOGI("dv_enable:%s\n", dinfo->amdv_enable); |
| |
| char ubootenv_amdv_type[MESON_MODE_LEN]; |
| ret = getBootEnv(UBOOTENV_USER_DV_TYPE, ubootenv_amdv_type); |
| if (ret) { |
| strcpy(dinfo->ubootenv_amdv_type, ubootenv_amdv_type); |
| } else if (isMboxSupportDV()) { |
| strcpy(dinfo->ubootenv_amdv_type, "1"); |
| } else { |
| strcpy(dinfo->ubootenv_amdv_type, "0"); |
| } |
| MESON_LOGI("ubootenv_dv_type:%s\n", dinfo->ubootenv_amdv_type); |
| } |
| |
| void ModePolicy::drmMode2MesonMode(meson_mode_info_t &mesonMode, drm_mode_info_t &drmMode) { |
| strncpy(mesonMode.name, drmMode.name, MESON_MODE_LEN); |
| mesonMode.dpi_x = drmMode.dpiX; |
| mesonMode.dpi_y = drmMode.dpiY; |
| mesonMode.pixel_w = drmMode.pixelW; |
| mesonMode.pixel_h = drmMode.pixelH; |
| mesonMode.refresh_rate = drmMode.refreshRate; |
| mesonMode.group_id = drmMode.groupId; |
| } |
| |
| void ModePolicy::getSupportedModes() { |
| //pthread_mutex_lock(&mEnvLock); |
| std::map<uint32_t, drm_mode_info_t> connecterModeList; |
| |
| /* reset ModeList */ |
| mModes.clear(); |
| if (mConnector->connection == DRM_MODE_CONNECTED) { |
| getModes(mConnector, connecterModeList); |
| |
| for (auto it = connecterModeList.begin(); it != connecterModeList.end(); it++) { |
| // All modes are supported |
| if (isModeSupported(it->second)) { |
| mModes.emplace(mModes.size(), it->second); |
| } |
| } |
| } |
| |
| /* transfer to meson_mode_info_t */ |
| auto conPtr = &mConData.con_info; |
| conPtr->modes_size = mModes.size(); |
| if (conPtr->modes_size > conPtr->modes_capacity) { |
| // realloc memory |
| void * buff = realloc(conPtr->modes, conPtr->modes_size * sizeof(meson_mode_info_t)); |
| MESON_ASSERT(buff, "modePolicy realloc but has no memory"); |
| conPtr->modes = (meson_mode_info_t *) buff; |
| conPtr->modes_capacity = conPtr->modes_size; |
| } |
| |
| loadVrrModeGroups(); |
| groupDisplayModes(); |
| |
| int i = 0; |
| for (auto it = mModes.begin(); it != mModes.end(); it++) { |
| drmMode2MesonMode(conPtr->modes[i], it->second); |
| i++; |
| } |
| } |
| |
| bool ModePolicy::getModeNameForPix(char *name, |
| int32_t width, int32_t height, uint32_t refresh, uint32_t flags) |
| { |
| std::map<uint32_t, drm_mode_info_t> connecterModeList; |
| drm_mode_info_t mode; |
| int current_interlaced; |
| bool ret = false; |
| |
| if (!mConnector || mConnector->connection != DRM_MODE_CONNECTED) |
| return false; |
| |
| drmModeModeInfoPtr drmModes = mConnector->modes; |
| |
| for (int i = 0;i < mConnector->count_modes; i++) { |
| current_interlaced = (drmModes[i].flags & DRM_MODE_FLAG_INTERLACE); |
| if (drmModes[i].hdisplay == width && drmModes[i].vdisplay == height && |
| drmModes[i].vrefresh == refresh && |
| current_interlaced == (flags & DRM_MODE_FLAG_INTERLACE)) { |
| strcpy(name, drmModes[i].name); |
| ret = true; |
| break; |
| } |
| } |
| return ret; |
| } |
| |
| bool ModePolicy::isModeSupported(drm_mode_info_t mode) { |
| bool ret = false; |
| uint32_t i; |
| |
| for (i = 0; i < ARRAY_SIZE(DISPLAY_MODE_LIST); i++) { |
| if (!strcmp(DISPLAY_MODE_LIST[i], mode.name)) { |
| ret = true; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| bool ModePolicy::isSeamlessMode(const drm_mode_info_t & mode, const drm_mode_info_t &groupMode) |
| { |
| if (mHdrCapabilities.AMDV_4K30_Supported == 1) { |
| if (mode.pixelW == FB_SIZE_4K_W && mode.pixelH == FB_SIZE_4K_H) { |
| auto refreshA = ceilf(mode.refreshRate); |
| auto refreshB = ceilf(groupMode.refreshRate); |
| if ((refreshA > REFRESH_RATE_30 && refreshB <= REFRESH_RATE_30) || |
| (refreshA <= REFRESH_RATE_30 && refreshB > REFRESH_RATE_30)) { |
| return false; |
| } |
| } |
| } |
| |
| for (int32_t i = 0; i < mVrrModeGroup.num; i++) { |
| if (mVrrModeGroup.groups[i].width == mode.pixelW |
| && mVrrModeGroup.groups[i].height == mode.pixelH) { |
| MESON_LOGD("mVrrModeGroup: w %d h %d mode: W %d H %d refreshRate %d\n", |
| mVrrModeGroup.groups[i].width,mVrrModeGroup.groups[i].height,mode.pixelW,mode.pixelH,mode.refreshRate); |
| if (((mode.refreshRate - mVrrModeGroup.groups[i].vrr_min) >= 0 |
| //frac refresh rate |
| || std::abs(mode.refreshRate - (mVrrModeGroup.groups[i].vrr_min * 1000) / (float)1001) < 0.001) |
| && (mode.refreshRate - mVrrModeGroup.groups[i].vrr_max <= 0)) { |
| if (mVrrModeGroup.groups[i].width == groupMode.pixelW |
| && mVrrModeGroup.groups[i].height == groupMode.pixelH) { |
| MESON_LOGD("groupMode: W %d H %d refreshRate %d\n", |
| groupMode.pixelW,groupMode.pixelH,groupMode.refreshRate); |
| if (((groupMode.refreshRate - mVrrModeGroup.groups[i].vrr_min) >= 0 |
| //frac refresh rate |
| || std::abs(groupMode.refreshRate - (mVrrModeGroup.groups[i].vrr_min * 1000) / (float)1001) < 0.001) |
| && (groupMode.refreshRate - mVrrModeGroup.groups[i].vrr_max <= 0)) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| } |
| } |
| return false; |
| } |
| |
| bool ModePolicy::supportVrr() |
| { |
| std::string vrr_cap; |
| getDisplayAttribute(DISPLAY_VRR_SUPPORTED, vrr_cap); |
| if (atoi(vrr_cap.c_str()) == 1) |
| return true; |
| return false; |
| } |
| |
| int32_t ModePolicy::loadVrrModeGroups() |
| { |
| if (!(mDisplayType == DISPLAY_TYPE_TV)) { |
| if (!(supportVrr()) || !mSeamlessSwitchEnabled) { |
| return 0; |
| } |
| } |
| |
| memset(&mVrrModeGroup, 0, sizeof(mVrrModeGroup)); |
| mVrrModeGroup.conn_id = mConnector->connector_id; |
| auto ret = ioctl(mDrmFd, DRM_IOCTL_MESON_GET_VRR_RANGE, &mVrrModeGroup); |
| |
| MESON_LOGD("\n %s %d conn_id:%d mDrmFd:%d mVrrModeGroup.num:%d\n",__FUNCTION__,__LINE__, mVrrModeGroup.conn_id, mDrmFd, mVrrModeGroup.num); |
| if (ret) { |
| MESON_LOGE("DRM_IOCTL_MESON_GET_VRR_RANGE error ret %d %s(%d)", ret, strerror(errno), errno); |
| return -EINVAL; |
| } |
| |
| return 0; |
| } |
| |
| bool ModePolicy::isVrrGroupedMode(const drm_mode_info_t & mode) |
| { |
| bool ret = true; |
| int count = 0; |
| drm_mode_info_t mesonMode = { |
| .name = "INVALID_MODE", |
| .dpiX = 0, |
| .dpiY = 0, |
| .pixelW = 0, |
| .pixelH = 0, |
| .refreshRate = 0, |
| .groupId = 0, |
| }; |
| for (auto it = mModes.begin(); it != mModes.end(); ++it) { |
| MESON_LOGD("\n isVrrGroupedMode:mode name: %s mModes name:%s\n", mode.name, it->second.name); |
| if (strncmp(it->second.name, mode.name, DRM_DISPLAY_MODE_LEN) == 0) { |
| mesonMode = it->second; |
| break; |
| } |
| } |
| for (auto it = mModes.begin(); it != mModes.end(); ++it) { |
| MESON_LOGD("\n isVrrGroupedMode:mode(%d %d) mModes(%d %d) group id:(%d %d)\n", |
| mesonMode.pixelW, mesonMode.pixelH, it->second.pixelW, it->second.pixelH, mesonMode.groupId ,it->second.groupId); |
| if (it->second.pixelW == mesonMode.pixelW && it->second.pixelH == mesonMode.pixelH |
| && mesonMode.groupId == it->second.groupId) { |
| count++; |
| } |
| } |
| if (count <= 1) |
| ret = false; |
| return ret; |
| } |
| |
| int32_t ModePolicy::getDrmModeInfoFromName(char* name , drm_mode_info_t* drmMode) |
| { |
| int ret = -1; |
| if (!name || !drmMode) { |
| MESON_LOGE("\n invalid parameter\n"); |
| return ret; |
| } |
| for (auto & mode : mModes) { |
| auto & itMode = mode.second; |
| if ( strcmp (itMode.name, name) ==0 ) { |
| *drmMode = itMode; |
| ret = 0; |
| break; |
| } |
| } |
| return ret; |
| } |
| |
| int32_t ModePolicy::groupDisplayModes() |
| { |
| /* no need to regenerate groupId if without QMS/VRR support */ |
| if ( mDisplayType != DISPLAY_TYPE_TV) { |
| if (!(supportVrr()) || !mSeamlessSwitchEnabled) { |
| return 0; |
| } |
| } |
| /* clear the old group modes */ |
| mMesonGroupModes.clear(); |
| |
| for (auto & mode : mModes) { |
| auto & itMode = mode.second; |
| bool needRegroup = true; |
| for (auto & groupModes : mMesonGroupModes) { |
| int groupId = groupModes.first; |
| auto& itGroupModes = groupModes.second; |
| |
| // do not check interlace mode, |
| // interlace mode does not support vrr |
| if (strstr(itMode.name, "i") != NULL) |
| break; |
| |
| // only support resolution >= 720P |
| if (itMode.pixelW < 1280 || itMode.pixelH < 720) |
| break; |
| |
| if (!itGroupModes.empty()) { |
| /* only need check the first item*/ |
| drm_mode_info_t *gmodePtr = itGroupModes[0]; |
| MESON_LOGD("gmodePtr: W %d H %d itMode: W %d H %d\n",gmodePtr->pixelW, |
| gmodePtr->pixelH,itMode.pixelW,itMode.pixelH); |
| if (gmodePtr->pixelW == itMode.pixelW && gmodePtr->pixelH == itMode.pixelH |
| && isSeamlessMode(itMode, *gmodePtr)) { |
| itMode.groupId = groupId; |
| itGroupModes.push_back(&itMode); |
| needRegroup = false; |
| break; |
| } |
| } |
| } |
| |
| if (needRegroup) { |
| itMode.groupId = mMesonGroupModes.size(); |
| auto iter = mMesonGroupModes.emplace(mMesonGroupModes.size(), |
| std::vector<drm_mode_info_t *> ()); |
| auto & modesWithSameGroup = iter.first->second; |
| modesWithSameGroup.push_back(&itMode); |
| } |
| } |
| |
| return 0; |
| } |
| |
| void ModePolicy::updateDrmfd(int drmFd) |
| { |
| MESON_LOGD("updateDrmfd:%d\n", drmFd); |
| if (drmFd >= 0) |
| mDrmFd = drmFd; |
| } |
| |
| void ModePolicy::seamlessSwitchEnabled(bool enable) |
| { |
| MESON_LOGD("seamlessSwitchEnabled:%d\n", enable); |
| mSeamlessSwitchEnabled = enable; |
| } |
| |
| void ModePolicy::seamlessSwitchQmsEnabled(bool enable) |
| { |
| seamlessSwitchEnabled(enable); |
| setSourceDisplay(OUTPUT_MODE_STATE_POWER); |
| applyDisplaySetting(true); |
| } |
| |
| void ModePolicy::setQMSVRR(char* curDisplayMode, char* final_displaymode ) |
| { |
| if (!curDisplayMode || !final_displaymode) { |
| MESON_LOGE("\n %s %d invalid parameter\n", __FUNCTION__,__LINE__); |
| return; |
| } |
| drm_mode_info_t curDrmMode; |
| drm_mode_info_t finalDrmMode; |
| bool isSeamless = false; |
| getDrmModeInfoFromName(curDisplayMode, &curDrmMode); |
| getDrmModeInfoFromName(final_displaymode, &finalDrmMode); |
| isSeamless = (curDrmMode.groupId == finalDrmMode.groupId); |
| MESON_LOGD("\n %s %d curDisplayMode:%s, final_displaymode:%s isSeamless:%d\n", |
| __FUNCTION__,__LINE__, curDisplayMode, final_displaymode, isSeamless); |
| int enableVrr = 0; |
| int updateBrr = isSeamless ? 0 : 1; |
| char sEnableVrr[3] = {'\0'}; |
| char sUpdateBrr[3] = {'\0'}; |
| if (supportVrr()) { |
| bool modeIsVrrMode = true; |
| if (updateBrr) { |
| modeIsVrrMode = isVrrGroupedMode(finalDrmMode); |
| } |
| enableVrr = (mSeamlessSwitchEnabled && modeIsVrrMode) ? 1 : 0; |
| sprintf(sUpdateBrr, "%d",updateBrr); |
| MESON_LOGD("\n %s %d mSeamlessSwitchEnabled:%d, modeIsVrrMode:%d enableVrr:%d, updateBrr:%d\n", |
| __FUNCTION__,__LINE__, mSeamlessSwitchEnabled, modeIsVrrMode, enableVrr, updateBrr); |
| setDisplayAttribute(DISPLAY_BRR_UPDATE, sUpdateBrr); |
| } |
| sprintf(sEnableVrr, "%d",enableVrr); |
| setDisplayAttribute(DISPLAY_VRR_ENABLED, sEnableVrr); |
| |
| setDisplayAttribute(DISPLAY_UPDATE, "1"); |
| } |
| int32_t bindCrtcAndConnector(drmModeCrtc *crtc, drmModeConnector *conn) |
| { |
| int ret = -1; |
| MESON_LOGI("bindCrtcAndConnector:%p, %p\n", crtc, conn); |
| if (g_Policy.get()) { |
| ret = g_Policy->bindConnector(conn); |
| ret |= g_Policy->bindCrtc(crtc); |
| } |
| return ret; |
| } |
| |
| void initModePolicyFun(drmModeCrtc *crtc, drmModeConnector *conn, CompositorFunctionCallBack callback) |
| { |
| if (!g_Adapter.get()) |
| g_Adapter = std::make_shared<DisplayAdapter>(crtc, conn); |
| |
| if (!g_Policy.get()) |
| g_Policy = std::make_shared<ModePolicy>(g_Adapter, 0); |
| |
| if (g_Policy.get() && g_Adapter.get()) { |
| g_Adapter->registerCallBack(callback); |
| bindCrtcAndConnector(crtc, conn); |
| } |
| } |
| |
| void initModePolicy(drmModeCrtc *crtc, drmModeConnector *conn, CompositorFunctionCallBack callback) |
| { |
| //initModePolicyFun(crtc, conn,callback); |
| if (g_Policy.get()) { |
| g_Policy->initialize(); |
| } |
| } |
| |
| void onHotplug(bool connected) |
| { |
| if (g_Policy.get()) |
| g_Policy->onHotplug(connected); |
| } |
| |
| void getPreferredBootConfig(char *name) |
| { |
| std::string mode; |
| if (g_Policy.get()) { |
| if (g_Policy->getPreferredBootConfig(mode) == 0) |
| strcpy(name, mode.c_str()); |
| } |
| } |
| |
| void setHdrConversionPolicy(bool passthrough, int32_t forceType) |
| { |
| if (g_Policy.get()) |
| g_Policy->setHdrConversionPolicy(passthrough, forceType); |
| } |
| |
| void setDvMode(int amdv_mode) |
| { |
| std::string mode = to_string(amdv_mode); |
| if (g_Policy.get()) |
| g_Policy->setDvMode(mode); |
| } |
| |
| void setColorSpace(char *colorspace) |
| { |
| std::string color = colorspace; |
| if (g_Policy.get()) |
| g_Policy->setColorSpace(color); |
| } |
| |
| void setBootConfig(char *mode, bool auto_mode) |
| { |
| std::string config = mode; |
| if (g_Policy.get()) { |
| if (auto_mode) |
| g_Policy->clearBootConfig(); |
| else |
| g_Policy->setBootConfig(config); |
| } |
| } |
| |
| bool setActiveConfig(char *mode) |
| { |
| std::string config = mode; |
| if (g_Policy.get()) { |
| g_Policy->setActiveConfig(config); |
| return true; |
| } |
| return false; |
| } |
| |
| bool setPolicyByAppName(const char *name, int state) |
| { |
| MESON_LOGD("\n %s %d name:%s state:%d \n", __FUNCTION__,__LINE__,name,state); |
| if (g_Policy.get()) { |
| if (state == 1 && !strcmp(name, "netflix")) { |
| g_Policy->setPolicy(MESON_POLICY_FRAMERATE); |
| } else { |
| g_Policy->setPolicy(MESON_POLICY_MIX); |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| bool updateEnv() |
| { |
| if (g_Policy.get()) |
| return g_Policy->updateEnv(); |
| return false; |
| } |
| |
| bool getModeNameForPix(char *name, |
| int32_t width, int32_t height, uint32_t refresh, uint32_t flags) |
| { |
| if (g_Policy.get()) |
| return g_Policy->getModeNameForPix(name, width, height, refresh / 1000, flags); |
| return false; |
| } |
| void updateDrmfd(int fd) |
| { |
| MESON_LOGD("\n %s %d fd:%d, g_Policy.get():%p\n",__FUNCTION__,__LINE__,fd, g_Policy.get()); |
| if (g_Policy.get()) |
| g_Policy->updateDrmfd(fd); |
| } |
| void seamlessSwitchEnabled(bool enable) |
| { |
| if (g_Policy.get()) |
| g_Policy->seamlessSwitchEnabled(enable); |
| } |
| |
| void seamlessSwitchQmsEnabled(bool enable) |
| { |
| if (g_Policy.get()) |
| g_Policy->seamlessSwitchQmsEnabled(enable); |
| } |
| |
| int setPriority(int priority) |
| { |
| if (g_Policy.get()) |
| return g_Policy->setHdrPriority(priority); |
| return -1; |
| } |
| |
| int getPriority() |
| { |
| if (g_Policy.get()) |
| return g_Policy->getHdrPriority(); |
| return 0; |
| } |