blob: 03fb3b858de4a025770a9ea31560977be024ad27 [file] [log] [blame]
/*
* 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;
}