leng.fang | 9185607 | 2024-06-07 14:12:54 +0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2022 Amlogic, Inc. All rights reserved. |
| 3 | * |
| 4 | * This source code is subject to the terms and conditions defined in the |
| 5 | * file 'LICENSE' which is part of this source code package. |
| 6 | * |
| 7 | * Description: |
| 8 | */ |
| 9 | |
| 10 | #include <sys/utsname.h> |
| 11 | |
| 12 | #include "DisplayAdapter.h" |
| 13 | |
| 14 | static int g_activeLevel= 3; |
| 15 | |
| 16 | bool update_sys_node_by_file(DisplayAttributeInfo& info, const string& in, string& out, UpdateType type) { |
| 17 | bool ret = false; |
| 18 | char buffer[MAX_BUF_LEN] = {0}; |
| 19 | int len; |
| 20 | const char* node = info.sysfs_node; |
| 21 | bool is_read_only = info.is_read_only; |
| 22 | bool is_write_only = info.is_write_only; |
| 23 | |
| 24 | switch (type) { |
| 25 | case UT_SET_VALUE: |
| 26 | if (is_read_only) |
| 27 | break; |
| 28 | info.new_value = in; |
| 29 | if (0 == sysfs_set_string(node, in.c_str())) { |
| 30 | info.current_value = in; |
| 31 | ret = true; |
| 32 | } |
| 33 | break; |
| 34 | case UT_GET_VALUE: |
| 35 | if (is_write_only) |
| 36 | break; |
| 37 | if (0 == sysfs_get_string(node, buffer, MAX_BUF_LEN)) { |
| 38 | out = buffer; |
| 39 | info.current_value = buffer; |
| 40 | ret = true; |
| 41 | } |
| 42 | break; |
| 43 | default: |
| 44 | break; |
| 45 | } |
| 46 | return ret; |
| 47 | } |
| 48 | |
| 49 | bool update_sys_node_by_property(DisplayAttributeInfo& info, const string& in, string& out, UpdateType type) { |
| 50 | bool ret = false; |
| 51 | char buffer[MAX_BUF_LEN] = {0}; |
| 52 | const char* node = info.sysfs_node; |
| 53 | bool is_read_only = info.is_read_only; |
| 54 | bool is_write_only = info.is_write_only; |
| 55 | |
| 56 | switch (type) { |
| 57 | case UT_SET_VALUE: |
| 58 | if (is_read_only) |
| 59 | break; |
| 60 | info.new_value = in; |
| 61 | if (info.callBack && info.callBack->set_property) { |
| 62 | info.callBack->set_property(info.obj_id, node, atoi(in.c_str())); |
| 63 | info.current_value = in; |
| 64 | ret = true; |
| 65 | } |
| 66 | break; |
| 67 | case UT_GET_VALUE: |
| 68 | if (is_write_only) |
| 69 | break; |
| 70 | if (info.callBack && info.callBack->get_property) { |
| 71 | if (info.callBack->get_property(info.obj_id, node, buffer) == 0) { |
| 72 | out = buffer; |
| 73 | info.current_value = buffer; |
| 74 | ret = true; |
| 75 | } |
| 76 | } |
| 77 | break; |
| 78 | default: |
| 79 | break; |
| 80 | } |
| 81 | return ret; |
| 82 | } |
| 83 | |
| 84 | DisplayAdapter::DisplayAdapter(drmModeCrtcPtr crtc, drmModeConnector *conn) { |
| 85 | initDisplayAttributeInfo(crtc, conn); |
| 86 | } |
| 87 | |
| 88 | void DisplayAdapter::initDisplayAttributeInfo(drmModeCrtcPtr crtc, drmModeConnector *conn) { |
| 89 | struct utsname buf; |
| 90 | int major = 0; |
| 91 | int minor = 0; |
| 92 | if (0 == uname(&buf)) { |
| 93 | if (sscanf(buf.release, "%d.%d", &major, &minor) != 2) { |
| 94 | major = 0; |
| 95 | } |
| 96 | } |
| 97 | if (major == 0) { |
| 98 | MESON_LOGV("Can't determine kernel version for access sysfs!"); |
| 99 | } |
| 100 | |
| 101 | #define DA_DEFINE(ID, INIT_VAL, UPDATE_FUN) \ |
| 102 | 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 } |
| 103 | |
| 104 | DA_DEFINE(AMDV_CAP, "0", update_sys_node_by_property); |
| 105 | DA_DEFINE(AMDV_CAP2, "0", update_sys_node_by_file); |
| 106 | DA_DEFINE(AMDV_ENABLE, "0", update_sys_node_by_property); |
| 107 | DA_DEFINE(AMDV_MODE, "0", update_sys_node_by_property); |
| 108 | DA_DEFINE(AMDV_STATUS, "0", update_sys_node_by_file); |
| 109 | DA_DEFINE(AMDV_POLICY, "0", update_sys_node_by_file); |
| 110 | DA_DEFINE(AMDV_LL_POLICY, "0", update_sys_node_by_file); |
| 111 | DA_DEFINE(AMDV_HDR_10_POLICY, "0", update_sys_node_by_file); |
| 112 | DA_DEFINE(AMDV_GRAPHICS_PRIORITY, "0", update_sys_node_by_file); |
| 113 | DA_DEFINE(HDR_CAP, "0", update_sys_node_by_property); |
| 114 | DA_DEFINE(HDR_CAP2, "0", update_sys_node_by_file); |
| 115 | DA_DEFINE(HDR_POLICY, "0", update_sys_node_by_property); |
| 116 | DA_DEFINE(HDR_MODE, "0", update_sys_node_by_file); |
| 117 | DA_DEFINE(SDR_MODE, "0", update_sys_node_by_file); |
| 118 | DA_DEFINE(HDMI_COLOR_ATTR, "0", update_sys_node_by_file); |
| 119 | DA_DEFINE(HDMI_AVMUTE, "0", update_sys_node_by_property); |
| 120 | DA_DEFINE(HDR_PRIORITY, "0", update_sys_node_by_file); |
| 121 | DA_DEFINE(FORCE_HDR_MODE, "0", update_sys_node_by_file); |
| 122 | DA_DEFINE(EDID_ATTR, "0", update_sys_node_by_property); |
| 123 | DA_DEFINE(FRAC_RATE_POLICY, "0", update_sys_node_by_property); |
| 124 | |
| 125 | #define DA_SET_NODE(ID, NODE) \ |
| 126 | display_attrs[DA_##ID].sysfs_node = NODE |
| 127 | if (major >= 5) { |
| 128 | DA_SET_NODE(AMDV_STATUS ,"/sys/module/aml_media/parameters/dolby_vision_status"); |
| 129 | DA_SET_NODE(AMDV_POLICY ,"/sys/module/aml_media/parameters/dolby_vision_policy"); |
| 130 | DA_SET_NODE(AMDV_LL_POLICY ,"/sys/module/aml_media/parameters/dolby_vision_ll_policy"); |
| 131 | DA_SET_NODE(AMDV_HDR_10_POLICY ,"/sys/module/aml_media/parameters/dolby_vision_hdr10_policy"); |
| 132 | DA_SET_NODE(AMDV_GRAPHICS_PRIORITY ,"/sys/module/aml_media/parameters/dolby_vision_graphics_priority"); |
| 133 | DA_SET_NODE(HDR_MODE ,"/sys/module/aml_media/parameters/hdr_mode"); |
| 134 | DA_SET_NODE(SDR_MODE ,"/sys/module/aml_media/parameters/sdr_mode"); |
| 135 | } else { |
| 136 | DA_SET_NODE(AMDV_STATUS ,"/sys/module/amdolby_vision/parameters/dolby_vision_status"); |
| 137 | DA_SET_NODE(AMDV_POLICY ,"/sys/module/amdolby_vision/parameters/dolby_vision_policy"); |
| 138 | DA_SET_NODE(AMDV_LL_POLICY ,"/sys/module/amdolby_vision/parameters/dolby_vision_ll_policy"); |
| 139 | DA_SET_NODE(AMDV_HDR_10_POLICY ,"/sys/module/amdolby_vision/parameters/dolby_vision_hdr10_policy"); |
| 140 | DA_SET_NODE(AMDV_GRAPHICS_PRIORITY ,"/sys/module/amdolby_vision/parameters/dolby_vision_graphics_priority"); |
| 141 | DA_SET_NODE(HDR_MODE ,"/sys/module/am_vecm/parameters/hdr_mode"); |
| 142 | DA_SET_NODE(SDR_MODE ,"/sys/module/am_vecm/parameters/sdr_mode"); |
| 143 | } |
| 144 | DA_SET_NODE(AMDV_CAP, "dv_cap"); |
| 145 | DA_SET_NODE(AMDV_CAP2, "/sys/class/amhdmitx/amhdmitx0/dv_cap2"); |
| 146 | DA_SET_NODE(AMDV_MODE, "dv_mode"); |
| 147 | DA_SET_NODE(HDR_CAP, "hdr_cap"); |
| 148 | DA_SET_NODE(HDR_CAP2, "/sys/class/amhdmitx/amhdmitx0/hdr_cap2"); |
| 149 | DA_SET_NODE(HDR_POLICY, "meson.crtc.hdr_policy"); |
| 150 | DA_SET_NODE(AMDV_ENABLE, "dv_enable"); |
| 151 | DA_SET_NODE(HDMI_COLOR_ATTR ,"/sys/class/amhdmitx/amhdmitx0/attr"); |
| 152 | DA_SET_NODE(HDMI_AVMUTE ,"MESON_DRM_HDMITX_PROP_AVMUTE"); |
| 153 | DA_SET_NODE(HDR_PRIORITY, "/sys/class/amhdmitx/amhdmitx0/hdr_priority_mode"); |
| 154 | DA_SET_NODE(FORCE_HDR_MODE, "/sys/module/aml_media/parameters/force_output"); |
| 155 | DA_SET_NODE(EDID_ATTR, "EDID"); |
| 156 | DA_SET_NODE(FRAC_RATE_POLICY, "FRAC_RATE_POLICY"); |
| 157 | |
| 158 | #define DA_SET_READ_ONLY(ID) \ |
| 159 | display_attrs[DA_##ID].is_read_only = true |
| 160 | DA_SET_READ_ONLY(AMDV_CAP); |
| 161 | DA_SET_READ_ONLY(AMDV_CAP2); |
| 162 | DA_SET_READ_ONLY(AMDV_STATUS); |
| 163 | DA_SET_READ_ONLY(HDR_CAP); |
| 164 | DA_SET_READ_ONLY(HDR_CAP2); |
| 165 | #define DA_SET_WRITE_ONLY(ID) \ |
| 166 | display_attrs[DA_##ID].is_write_only= true |
| 167 | // DA_SET_WRITE_ONLY(AMDV_MODE); |
| 168 | |
| 169 | #define DA_SET_OBJ_ID(ID, id) \ |
| 170 | display_attrs[DA_##ID].obj_id = id |
| 171 | if (conn) { |
| 172 | DA_SET_OBJ_ID(AMDV_CAP, conn->connector_id); |
| 173 | DA_SET_OBJ_ID(AMDV_CAP2, conn->connector_id); |
| 174 | DA_SET_OBJ_ID(HDR_CAP, conn->connector_id); |
| 175 | DA_SET_OBJ_ID(HDMI_AVMUTE, conn->connector_id); |
| 176 | DA_SET_OBJ_ID(EDID_ATTR, conn->connector_id); |
| 177 | DA_SET_OBJ_ID(FRAC_RATE_POLICY, conn->connector_id); |
| 178 | DA_SET_OBJ_ID(HDMI_COLOR_ATTR, conn->connector_id); |
| 179 | } |
| 180 | if (crtc) { |
| 181 | DA_SET_OBJ_ID(AMDV_MODE, crtc->crtc_id); |
| 182 | DA_SET_OBJ_ID(HDR_POLICY, crtc->crtc_id); |
| 183 | DA_SET_OBJ_ID(AMDV_ENABLE, crtc->crtc_id); |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | bool DisplayAdapter::getDisplayMode(char *mode) { |
| 188 | if (mCallBack.get_mode) |
| 189 | return mCallBack.get_mode(mode); |
| 190 | return false; |
| 191 | } |
| 192 | |
| 193 | bool DisplayAdapter::setDisplayMode(std::string &mode) { |
| 194 | char name[DRM_DISPLAY_MODE_LEN] = { 0 }; |
| 195 | |
| 196 | strncpy(name, mode.c_str(), DRM_DISPLAY_MODE_LEN - 1); |
| 197 | if (mCallBack.set_mode) |
| 198 | return mCallBack.set_mode(name); |
| 199 | return false; |
| 200 | } |
| 201 | |
| 202 | bool DisplayAdapter::setDisplayRect(int x, int y, int width, int height) { |
| 203 | if (mCallBack.set_scaling_position) |
| 204 | mCallBack.set_scaling_position(x, y, width, height); |
| 205 | return true; |
| 206 | } |
| 207 | |
| 208 | void DisplayAdapter::setColorAttribute(const char *attr) { |
| 209 | if (mCallBack.set_colorattribute) |
| 210 | mCallBack.set_colorattribute(attr); |
| 211 | } |
| 212 | |
| 213 | DisplayAttributeInfo* DisplayAdapter::getDisplayAttributeInfo(const std::string &name) |
| 214 | { |
| 215 | int i = 0; |
| 216 | for (i = 0; i < DA_DISPLAY_ATTRIBUTE__COUNT; i++) { |
| 217 | if (display_attrs[i].name == name) { |
| 218 | return &(display_attrs[i]); |
| 219 | } |
| 220 | } |
| 221 | return NULL; |
| 222 | } |
| 223 | |
| 224 | int32_t DisplayAdapter::setColorAttrProperty(DisplayAttributeInfo *info, const std::string & hdmiColorAttr) { |
| 225 | uint32_t color_depth_value = 0; |
| 226 | uint32_t color_space_value = 0; |
| 227 | int ret = -1; |
| 228 | |
| 229 | if (strstr(hdmiColorAttr.c_str(), "rgb")) { |
| 230 | color_space_value = 0; |
| 231 | } else if (strstr(hdmiColorAttr.c_str(), "422")) { |
| 232 | color_space_value = 1; |
| 233 | } else if (strstr(hdmiColorAttr.c_str(), "444")) { |
| 234 | color_space_value = 2; |
| 235 | } else if (strstr(hdmiColorAttr.c_str(), "420")) { |
| 236 | color_space_value = 3; |
| 237 | } |
| 238 | |
| 239 | if (strstr(hdmiColorAttr.c_str(), "8bit")) { |
| 240 | color_depth_value = 8; |
| 241 | } else if (strstr(hdmiColorAttr.c_str(), "10bit")) { |
| 242 | color_depth_value = 10; |
| 243 | } else if (strstr(hdmiColorAttr.c_str(), "12bit")) { |
| 244 | color_depth_value = 12; |
| 245 | } |
| 246 | |
| 247 | if (info->callBack && info->callBack->set_property) { |
| 248 | MESON_LOGD("set colorspace: %d, colordepth: %d", color_space_value, color_depth_value); |
| 249 | ret = info->callBack->set_property(info->obj_id, "color_space", color_space_value); |
| 250 | ret |= info->callBack->set_property(info->obj_id, "color_depth", color_depth_value); |
| 251 | } |
| 252 | return ret; |
| 253 | } |
| 254 | |
| 255 | bool DisplayAdapter::setDisplayAttribute(const string& name, const string& value) { |
| 256 | DisplayAttributeInfo *info = getDisplayAttributeInfo(name); |
| 257 | if (!info) |
| 258 | return false; |
| 259 | |
| 260 | if (!strcmp(info->name, DISPLAY_HDMI_COLOR_ATTR)) { |
| 261 | return setColorAttrProperty(info, value) == 0; |
| 262 | } |
| 263 | |
| 264 | string out; |
| 265 | return info->update_fun(*info, value, out, UT_SET_VALUE); |
| 266 | } |
| 267 | |
| 268 | bool DisplayAdapter::getColorAttrProperty(DisplayAttributeInfo *info, std::string& attribute) { |
| 269 | char buffer[MAX_BUF_LEN] = {0}; |
| 270 | std::string colorSpace_str; |
| 271 | |
| 272 | if (info->callBack && info->callBack->get_property) { |
| 273 | if (info->callBack->get_property(info->obj_id, "color_space", buffer) == 0) { |
| 274 | switch (atoi(buffer)) { |
| 275 | case 0: |
| 276 | colorSpace_str = "rgb"; |
| 277 | break; |
| 278 | case 1: |
| 279 | colorSpace_str = "422"; |
| 280 | break; |
| 281 | case 2: |
| 282 | colorSpace_str = "444"; |
| 283 | break; |
| 284 | case 3: |
| 285 | colorSpace_str = "420"; |
| 286 | break; |
| 287 | default: |
| 288 | MESON_LOGE(" invalid colorSpace:%s", buffer); |
| 289 | break; |
| 290 | } |
| 291 | } else { |
| 292 | colorSpace_str = "rgb"; |
| 293 | } |
| 294 | memset(buffer, 0, MAX_BUF_LEN); |
| 295 | if (info->callBack->get_property(info->obj_id, "color_depth", buffer) < 0) |
| 296 | strcpy(buffer, "8"); |
| 297 | attribute = colorSpace_str + "," + std::to_string(atoi(buffer)) + "bit"; |
| 298 | MESON_LOGD(" colorSpace,colorDepth: %s", attribute.c_str()); |
| 299 | return true; |
| 300 | } |
| 301 | return false; |
| 302 | } |
| 303 | |
| 304 | bool DisplayAdapter::getDisplayAttribute(const string& name, string& value) { |
| 305 | DisplayAttributeInfo *info = getDisplayAttributeInfo(name); |
| 306 | bool ret = false; |
| 307 | string out = ""; |
| 308 | if (!info) |
| 309 | return false; |
| 310 | |
| 311 | if (!strcmp(info->name, DISPLAY_HDMI_COLOR_ATTR)) { |
| 312 | ret = getColorAttrProperty(info, value); |
| 313 | return ret; |
| 314 | } |
| 315 | |
| 316 | ret = info->update_fun(*info, "", out, UT_GET_VALUE); |
| 317 | if (ret) { |
| 318 | value = out; |
| 319 | } |
| 320 | return ret; |
| 321 | } |
| 322 | |
| 323 | void DisplayAdapter::registerCallBack(CompositorFunctionCallBack callback) { |
| 324 | mCallBack = callback; |
| 325 | } |
| 326 | |
| 327 | void DisplayAdapter::setLogLevel(int level) { |
| 328 | g_activeLevel = level; |
| 329 | } |