| /* |
| * 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 <sys/utsname.h> |
| |
| #include "DisplayAdapter.h" |
| |
| static int g_activeLevel= 3; |
| |
| bool update_sys_node_by_file(DisplayAttributeInfo& info, const string& in, string& out, UpdateType type) { |
| bool ret = false; |
| char buffer[MAX_BUF_LEN] = {0}; |
| int len; |
| const char* node = info.sysfs_node; |
| bool is_read_only = info.is_read_only; |
| bool is_write_only = info.is_write_only; |
| |
| switch (type) { |
| case UT_SET_VALUE: |
| if (is_read_only) |
| break; |
| info.new_value = in; |
| if (0 == sysfs_set_string(node, in.c_str())) { |
| info.current_value = in; |
| ret = true; |
| } |
| break; |
| case UT_GET_VALUE: |
| if (is_write_only) |
| break; |
| if (0 == sysfs_get_string(node, buffer, MAX_BUF_LEN)) { |
| out = buffer; |
| info.current_value = buffer; |
| ret = true; |
| } |
| break; |
| default: |
| break; |
| } |
| return ret; |
| } |
| |
| bool update_sys_node_by_property(DisplayAttributeInfo& info, const string& in, string& out, UpdateType type) { |
| bool ret = false; |
| char buffer[MAX_BUF_LEN] = {0}; |
| const char* node = info.sysfs_node; |
| bool is_read_only = info.is_read_only; |
| bool is_write_only = info.is_write_only; |
| |
| switch (type) { |
| case UT_SET_VALUE: |
| if (is_read_only) |
| break; |
| info.new_value = in; |
| if (info.callBack && info.callBack->set_property) { |
| info.callBack->set_property(info.obj_id, node, atoi(in.c_str())); |
| info.current_value = in; |
| ret = true; |
| } |
| break; |
| case UT_GET_VALUE: |
| if (is_write_only) |
| break; |
| if (info.callBack && info.callBack->get_property) { |
| if (info.callBack->get_property(info.obj_id, node, buffer) == 0) { |
| out = buffer; |
| info.current_value = buffer; |
| ret = true; |
| } |
| } |
| break; |
| default: |
| break; |
| } |
| return ret; |
| } |
| |
| DisplayAdapter::DisplayAdapter(drmModeCrtcPtr crtc, drmModeConnector *conn) { |
| initDisplayAttributeInfo(crtc, conn); |
| } |
| |
| void DisplayAdapter::initDisplayAttributeInfo(drmModeCrtcPtr crtc, drmModeConnector *conn) { |
| struct utsname buf; |
| int major = 0; |
| int minor = 0; |
| if (0 == uname(&buf)) { |
| if (sscanf(buf.release, "%d.%d", &major, &minor) != 2) { |
| major = 0; |
| } |
| } |
| if (major == 0) { |
| MESON_LOGV("Can't determine kernel version for access sysfs!"); |
| } |
| |
| #define DA_DEFINE(ID, INIT_VAL, UPDATE_FUN) \ |
| display_attrs[DA_##ID] = { .name = DISPLAY_##ID, .attr_id = DA_##ID, .current_value = INIT_VAL, .new_value = INIT_VAL, .status_flags = 0, .update_fun = UPDATE_FUN, .sysfs_node = NULL, .obj_id = 0, .is_read_only = false, .is_write_only = false, .callBack = &mCallBack } |
| |
| DA_DEFINE(AMDV_CAP, "0", update_sys_node_by_property); |
| DA_DEFINE(AMDV_CAP2, "0", update_sys_node_by_file); |
| DA_DEFINE(AMDV_ENABLE, "0", update_sys_node_by_property); |
| DA_DEFINE(AMDV_MODE, "0", update_sys_node_by_property); |
| DA_DEFINE(AMDV_STATUS, "0", update_sys_node_by_file); |
| DA_DEFINE(AMDV_POLICY, "0", update_sys_node_by_file); |
| DA_DEFINE(AMDV_LL_POLICY, "0", update_sys_node_by_file); |
| DA_DEFINE(AMDV_HDR_10_POLICY, "0", update_sys_node_by_file); |
| DA_DEFINE(AMDV_GRAPHICS_PRIORITY, "0", update_sys_node_by_file); |
| DA_DEFINE(HDR_CAP, "0", update_sys_node_by_property); |
| DA_DEFINE(HDR_CAP2, "0", update_sys_node_by_file); |
| DA_DEFINE(HDR_POLICY, "0", update_sys_node_by_property); |
| DA_DEFINE(HDR_MODE, "0", update_sys_node_by_file); |
| DA_DEFINE(SDR_MODE, "0", update_sys_node_by_file); |
| DA_DEFINE(HDMI_COLOR_ATTR, "0", update_sys_node_by_file); |
| DA_DEFINE(HDMI_AVMUTE, "0", update_sys_node_by_property); |
| DA_DEFINE(HDR_PRIORITY, "0", update_sys_node_by_file); |
| DA_DEFINE(FORCE_HDR_MODE, "0", update_sys_node_by_file); |
| DA_DEFINE(EDID_ATTR, "0", update_sys_node_by_property); |
| DA_DEFINE(FRAC_RATE_POLICY, "0", update_sys_node_by_property); |
| DA_DEFINE(VRR_SUPPORTED, "0", update_sys_node_by_property); |
| DA_DEFINE(VRR_ENABLED, "0", update_sys_node_by_property); |
| DA_DEFINE(BRR_UPDATE, "0", update_sys_node_by_property); |
| |
| #define DA_SET_NODE(ID, NODE) \ |
| display_attrs[DA_##ID].sysfs_node = NODE |
| if (major >= 5) { |
| DA_SET_NODE(AMDV_STATUS ,"/sys/module/aml_media/parameters/dolby_vision_status"); |
| DA_SET_NODE(AMDV_POLICY ,"/sys/module/aml_media/parameters/dolby_vision_policy"); |
| DA_SET_NODE(AMDV_LL_POLICY ,"/sys/module/aml_media/parameters/dolby_vision_ll_policy"); |
| DA_SET_NODE(AMDV_HDR_10_POLICY ,"/sys/module/aml_media/parameters/dolby_vision_hdr10_policy"); |
| DA_SET_NODE(AMDV_GRAPHICS_PRIORITY ,"/sys/module/aml_media/parameters/dolby_vision_graphics_priority"); |
| DA_SET_NODE(HDR_MODE ,"/sys/module/aml_media/parameters/hdr_mode"); |
| DA_SET_NODE(SDR_MODE ,"/sys/module/aml_media/parameters/sdr_mode"); |
| } else { |
| DA_SET_NODE(AMDV_STATUS ,"/sys/module/amdolby_vision/parameters/dolby_vision_status"); |
| DA_SET_NODE(AMDV_POLICY ,"/sys/module/amdolby_vision/parameters/dolby_vision_policy"); |
| DA_SET_NODE(AMDV_LL_POLICY ,"/sys/module/amdolby_vision/parameters/dolby_vision_ll_policy"); |
| DA_SET_NODE(AMDV_HDR_10_POLICY ,"/sys/module/amdolby_vision/parameters/dolby_vision_hdr10_policy"); |
| DA_SET_NODE(AMDV_GRAPHICS_PRIORITY ,"/sys/module/amdolby_vision/parameters/dolby_vision_graphics_priority"); |
| DA_SET_NODE(HDR_MODE ,"/sys/module/am_vecm/parameters/hdr_mode"); |
| DA_SET_NODE(SDR_MODE ,"/sys/module/am_vecm/parameters/sdr_mode"); |
| } |
| DA_SET_NODE(AMDV_CAP, "dv_cap"); |
| DA_SET_NODE(AMDV_CAP2, "/sys/class/amhdmitx/amhdmitx0/dv_cap2"); |
| DA_SET_NODE(AMDV_MODE, "dv_mode"); |
| DA_SET_NODE(HDR_CAP, "hdr_cap"); |
| DA_SET_NODE(HDR_CAP2, "/sys/class/amhdmitx/amhdmitx0/hdr_cap2"); |
| DA_SET_NODE(HDR_POLICY, "meson.crtc.hdr_policy"); |
| DA_SET_NODE(AMDV_ENABLE, "dv_enable"); |
| DA_SET_NODE(HDMI_COLOR_ATTR ,"/sys/class/amhdmitx/amhdmitx0/attr"); |
| DA_SET_NODE(HDMI_AVMUTE ,"MESON_DRM_HDMITX_PROP_AVMUTE"); |
| DA_SET_NODE(HDR_PRIORITY, "/sys/class/amhdmitx/amhdmitx0/hdr_priority_mode"); |
| DA_SET_NODE(FORCE_HDR_MODE, "/sys/module/aml_media/parameters/force_output"); |
| DA_SET_NODE(EDID_ATTR, "EDID"); |
| DA_SET_NODE(FRAC_RATE_POLICY, "FRAC_RATE_POLICY"); |
| DA_SET_NODE(VRR_SUPPORTED, "vrr_capable"); |
| DA_SET_NODE(VRR_ENABLED, "VRR_ENABLED"); |
| DA_SET_NODE(BRR_UPDATE, "brr_update"); |
| |
| #define DA_SET_READ_ONLY(ID) \ |
| display_attrs[DA_##ID].is_read_only = true |
| DA_SET_READ_ONLY(AMDV_CAP); |
| DA_SET_READ_ONLY(AMDV_CAP2); |
| DA_SET_READ_ONLY(AMDV_STATUS); |
| DA_SET_READ_ONLY(HDR_CAP); |
| DA_SET_READ_ONLY(HDR_CAP2); |
| DA_SET_READ_ONLY(VRR_SUPPORTED); |
| #define DA_SET_WRITE_ONLY(ID) \ |
| display_attrs[DA_##ID].is_write_only= true |
| // DA_SET_WRITE_ONLY(AMDV_MODE); |
| |
| #define DA_SET_OBJ_ID(ID, id) \ |
| display_attrs[DA_##ID].obj_id = id |
| if (conn) { |
| DA_SET_OBJ_ID(AMDV_CAP, conn->connector_id); |
| DA_SET_OBJ_ID(AMDV_CAP2, conn->connector_id); |
| DA_SET_OBJ_ID(HDR_CAP, conn->connector_id); |
| DA_SET_OBJ_ID(HDMI_AVMUTE, conn->connector_id); |
| DA_SET_OBJ_ID(EDID_ATTR, conn->connector_id); |
| DA_SET_OBJ_ID(FRAC_RATE_POLICY, conn->connector_id); |
| DA_SET_OBJ_ID(HDMI_COLOR_ATTR, conn->connector_id); |
| DA_SET_OBJ_ID(VRR_SUPPORTED, conn->connector_id); |
| } |
| if (crtc) { |
| DA_SET_OBJ_ID(AMDV_MODE, crtc->crtc_id); |
| DA_SET_OBJ_ID(HDR_POLICY, crtc->crtc_id); |
| DA_SET_OBJ_ID(AMDV_ENABLE, crtc->crtc_id); |
| DA_SET_OBJ_ID(VRR_ENABLED, crtc->crtc_id); |
| DA_SET_OBJ_ID(BRR_UPDATE, crtc->crtc_id); |
| } |
| } |
| |
| bool DisplayAdapter::getDisplayMode(char *mode) { |
| if (mCallBack.get_mode) |
| return mCallBack.get_mode(mode); |
| return false; |
| } |
| |
| bool DisplayAdapter::setDisplayMode(std::string &mode) { |
| char name[DRM_DISPLAY_MODE_LEN] = { 0 }; |
| |
| strncpy(name, mode.c_str(), DRM_DISPLAY_MODE_LEN - 1); |
| if (mCallBack.set_mode) |
| return mCallBack.set_mode(name); |
| return false; |
| } |
| |
| bool DisplayAdapter::setDisplayRect(int x, int y, int width, int height) { |
| if (mCallBack.set_scaling_position) |
| mCallBack.set_scaling_position(x, y, width, height); |
| return true; |
| } |
| |
| void DisplayAdapter::setColorAttribute(const char *attr) { |
| if (mCallBack.set_colorattribute) |
| mCallBack.set_colorattribute(attr); |
| } |
| |
| DisplayAttributeInfo* DisplayAdapter::getDisplayAttributeInfo(const std::string &name) |
| { |
| int i = 0; |
| for (i = 0; i < DA_DISPLAY_ATTRIBUTE__COUNT; i++) { |
| if (display_attrs[i].name == name) { |
| return &(display_attrs[i]); |
| } |
| } |
| return NULL; |
| } |
| |
| int32_t DisplayAdapter::setColorAttrProperty(DisplayAttributeInfo *info, const std::string & hdmiColorAttr) { |
| uint32_t color_depth_value = 0; |
| uint32_t color_space_value = 0; |
| int ret = -1; |
| |
| if (strstr(hdmiColorAttr.c_str(), "rgb")) { |
| color_space_value = 0; |
| } else if (strstr(hdmiColorAttr.c_str(), "422")) { |
| color_space_value = 1; |
| } else if (strstr(hdmiColorAttr.c_str(), "444")) { |
| color_space_value = 2; |
| } else if (strstr(hdmiColorAttr.c_str(), "420")) { |
| color_space_value = 3; |
| } |
| |
| if (strstr(hdmiColorAttr.c_str(), "8bit")) { |
| color_depth_value = 8; |
| } else if (strstr(hdmiColorAttr.c_str(), "10bit")) { |
| color_depth_value = 10; |
| } else if (strstr(hdmiColorAttr.c_str(), "12bit")) { |
| color_depth_value = 12; |
| } |
| |
| if (info->callBack && info->callBack->set_property) { |
| MESON_LOGD("set colorspace: %d, colordepth: %d", color_space_value, color_depth_value); |
| ret = info->callBack->set_property(info->obj_id, "color_space", color_space_value); |
| ret |= info->callBack->set_property(info->obj_id, "color_depth", color_depth_value); |
| } |
| return ret; |
| } |
| |
| bool DisplayAdapter::setDisplayAttribute(const string& name, const string& value) { |
| DisplayAttributeInfo *info = getDisplayAttributeInfo(name); |
| if (!info) |
| return false; |
| |
| if (!strcmp(info->name, DISPLAY_HDMI_COLOR_ATTR)) { |
| return setColorAttrProperty(info, value) == 0; |
| } |
| |
| string out; |
| return info->update_fun(*info, value, out, UT_SET_VALUE); |
| } |
| |
| bool DisplayAdapter::getColorAttrProperty(DisplayAttributeInfo *info, std::string& attribute) { |
| char buffer[MAX_BUF_LEN] = {0}; |
| std::string colorSpace_str; |
| |
| if (info->callBack && info->callBack->get_property) { |
| if (info->callBack->get_property(info->obj_id, "color_space", buffer) == 0) { |
| switch (atoi(buffer)) { |
| case 0: |
| colorSpace_str = "rgb"; |
| break; |
| case 1: |
| colorSpace_str = "422"; |
| break; |
| case 2: |
| colorSpace_str = "444"; |
| break; |
| case 3: |
| colorSpace_str = "420"; |
| break; |
| default: |
| MESON_LOGE(" invalid colorSpace:%s", buffer); |
| break; |
| } |
| } else { |
| colorSpace_str = "rgb"; |
| } |
| memset(buffer, 0, MAX_BUF_LEN); |
| if (info->callBack->get_property(info->obj_id, "color_depth", buffer) < 0) |
| strcpy(buffer, "8"); |
| attribute = colorSpace_str + "," + std::to_string(atoi(buffer)) + "bit"; |
| MESON_LOGD(" colorSpace,colorDepth: %s", attribute.c_str()); |
| return true; |
| } |
| return false; |
| } |
| |
| bool DisplayAdapter::getDisplayAttribute(const string& name, string& value) { |
| DisplayAttributeInfo *info = getDisplayAttributeInfo(name); |
| bool ret = false; |
| string out = ""; |
| if (!info) |
| return false; |
| |
| if (!strcmp(info->name, DISPLAY_HDMI_COLOR_ATTR)) { |
| ret = getColorAttrProperty(info, value); |
| return ret; |
| } |
| |
| ret = info->update_fun(*info, "", out, UT_GET_VALUE); |
| if (ret) { |
| value = out; |
| } |
| return ret; |
| } |
| |
| void DisplayAdapter::registerCallBack(CompositorFunctionCallBack callback) { |
| mCallBack = callback; |
| } |
| |
| void DisplayAdapter::setLogLevel(int level) { |
| g_activeLevel = level; |
| } |