4187 lines · c
1/*2 * Copyright 2018 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26#include <linux/string_helpers.h>27#include <linux/uaccess.h>28 29#include "dc.h"30#include "amdgpu.h"31#include "amdgpu_dm.h"32#include "amdgpu_dm_debugfs.h"33#include "amdgpu_dm_replay.h"34#include "dm_helpers.h"35#include "dmub/dmub_srv.h"36#include "resource.h"37#include "dsc.h"38#include "link_hwss.h"39#include "dc/dc_dmub_srv.h"40#include "link/protocols/link_dp_capability.h"41#include "inc/hw/dchubbub.h"42 43#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY44#include "amdgpu_dm_psr.h"45#endif46 47struct dmub_debugfs_trace_header {48 uint32_t entry_count;49 uint32_t reserved[3];50};51 52struct dmub_debugfs_trace_entry {53 uint32_t trace_code;54 uint32_t tick_count;55 uint32_t param0;56 uint32_t param1;57};58 59static const char *const mst_progress_status[] = {60 "probe",61 "remote_edid",62 "allocate_new_payload",63 "clear_allocated_payload",64};65 66/* parse_write_buffer_into_params - Helper function to parse debugfs write buffer into an array67 *68 * Function takes in attributes passed to debugfs write entry69 * and writes into param array.70 * The user passes max_param_num to identify maximum number of71 * parameters that could be parsed.72 *73 */74static int parse_write_buffer_into_params(char *wr_buf, uint32_t wr_buf_size,75 long *param, const char __user *buf,76 int max_param_num,77 uint8_t *param_nums)78{79 char *wr_buf_ptr = NULL;80 uint32_t wr_buf_count = 0;81 int r;82 char *sub_str = NULL;83 const char delimiter[3] = {' ', '\n', '\0'};84 uint8_t param_index = 0;85 86 *param_nums = 0;87 88 wr_buf_ptr = wr_buf;89 90 /* r is bytes not be copied */91 if (copy_from_user(wr_buf_ptr, buf, wr_buf_size)) {92 DRM_DEBUG_DRIVER("user data could not be read successfully\n");93 return -EFAULT;94 }95 96 /* check number of parameters. isspace could not differ space and \n */97 while ((*wr_buf_ptr != 0xa) && (wr_buf_count < wr_buf_size)) {98 /* skip space*/99 while (isspace(*wr_buf_ptr) && (wr_buf_count < wr_buf_size)) {100 wr_buf_ptr++;101 wr_buf_count++;102 }103 104 if (wr_buf_count == wr_buf_size)105 break;106 107 /* skip non-space*/108 while ((!isspace(*wr_buf_ptr)) && (wr_buf_count < wr_buf_size)) {109 wr_buf_ptr++;110 wr_buf_count++;111 }112 113 (*param_nums)++;114 115 if (wr_buf_count == wr_buf_size)116 break;117 }118 119 if (*param_nums > max_param_num)120 *param_nums = max_param_num;121 122 wr_buf_ptr = wr_buf; /* reset buf pointer */123 wr_buf_count = 0; /* number of char already checked */124 125 while (isspace(*wr_buf_ptr) && (wr_buf_count < wr_buf_size)) {126 wr_buf_ptr++;127 wr_buf_count++;128 }129 130 while (param_index < *param_nums) {131 /* after strsep, wr_buf_ptr will be moved to after space */132 sub_str = strsep(&wr_buf_ptr, delimiter);133 134 r = kstrtol(sub_str, 16, &(param[param_index]));135 136 if (r)137 DRM_DEBUG_DRIVER("string to int convert error code: %d\n", r);138 139 param_index++;140 }141 142 return 0;143}144 145/* function description146 * get/ set DP configuration: lane_count, link_rate, spread_spectrum147 *148 * valid lane count value: 1, 2, 4149 * valid link rate value:150 * 06h = 1.62Gbps per lane151 * 0Ah = 2.7Gbps per lane152 * 0Ch = 3.24Gbps per lane153 * 14h = 5.4Gbps per lane154 * 1Eh = 8.1Gbps per lane155 *156 * debugfs is located at /sys/kernel/debug/dri/0/DP-x/link_settings157 *158 * --- to get dp configuration159 *160 * cat /sys/kernel/debug/dri/0/DP-x/link_settings161 *162 * It will list current, verified, reported, preferred dp configuration.163 * current -- for current video mode164 * verified --- maximum configuration which pass link training165 * reported --- DP rx report caps (DPCD register offset 0, 1 2)166 * preferred --- user force settings167 *168 * --- set (or force) dp configuration169 *170 * echo <lane_count> <link_rate> > link_settings171 *172 * for example, to force to 2 lane, 2.7GHz,173 * echo 4 0xa > /sys/kernel/debug/dri/0/DP-x/link_settings174 *175 * spread_spectrum could not be changed dynamically.176 *177 * in case invalid lane count, link rate are force, no hw programming will be178 * done. please check link settings after force operation to see if HW get179 * programming.180 *181 * cat /sys/kernel/debug/dri/0/DP-x/link_settings182 *183 * check current and preferred settings.184 *185 */186static ssize_t dp_link_settings_read(struct file *f, char __user *buf,187 size_t size, loff_t *pos)188{189 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;190 struct dc_link *link = connector->dc_link;191 char *rd_buf = NULL;192 char *rd_buf_ptr = NULL;193 const uint32_t rd_buf_size = 100;194 uint32_t result = 0;195 uint8_t str_len = 0;196 int r;197 198 if (*pos & 3 || size & 3)199 return -EINVAL;200 201 rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);202 if (!rd_buf)203 return 0;204 205 rd_buf_ptr = rd_buf;206 207 str_len = strlen("Current: %d 0x%x %d ");208 snprintf(rd_buf_ptr, str_len, "Current: %d 0x%x %d ",209 link->cur_link_settings.lane_count,210 link->cur_link_settings.link_rate,211 link->cur_link_settings.link_spread);212 rd_buf_ptr += str_len;213 214 str_len = strlen("Verified: %d 0x%x %d ");215 snprintf(rd_buf_ptr, str_len, "Verified: %d 0x%x %d ",216 link->verified_link_cap.lane_count,217 link->verified_link_cap.link_rate,218 link->verified_link_cap.link_spread);219 rd_buf_ptr += str_len;220 221 str_len = strlen("Reported: %d 0x%x %d ");222 snprintf(rd_buf_ptr, str_len, "Reported: %d 0x%x %d ",223 link->reported_link_cap.lane_count,224 link->reported_link_cap.link_rate,225 link->reported_link_cap.link_spread);226 rd_buf_ptr += str_len;227 228 str_len = strlen("Preferred: %d 0x%x %d ");229 snprintf(rd_buf_ptr, str_len, "Preferred: %d 0x%x %d\n",230 link->preferred_link_setting.lane_count,231 link->preferred_link_setting.link_rate,232 link->preferred_link_setting.link_spread);233 234 while (size) {235 if (*pos >= rd_buf_size)236 break;237 238 r = put_user(*(rd_buf + result), buf);239 if (r) {240 kfree(rd_buf);241 return r; /* r = -EFAULT */242 }243 244 buf += 1;245 size -= 1;246 *pos += 1;247 result += 1;248 }249 250 kfree(rd_buf);251 return result;252}253 254static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,255 size_t size, loff_t *pos)256{257 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;258 struct dc_link *link = connector->dc_link;259 struct amdgpu_device *adev = drm_to_adev(connector->base.dev);260 struct dc *dc = (struct dc *)link->dc;261 struct dc_link_settings prefer_link_settings;262 char *wr_buf = NULL;263 const uint32_t wr_buf_size = 40;264 /* 0: lane_count; 1: link_rate */265 int max_param_num = 2;266 uint8_t param_nums = 0;267 long param[2];268 bool valid_input = true;269 270 if (size == 0)271 return -EINVAL;272 273 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);274 if (!wr_buf)275 return -ENOSPC;276 277 if (parse_write_buffer_into_params(wr_buf, wr_buf_size,278 (long *)param, buf,279 max_param_num,280 ¶m_nums)) {281 kfree(wr_buf);282 return -EINVAL;283 }284 285 if (param_nums <= 0) {286 kfree(wr_buf);287 DRM_DEBUG_DRIVER("user data not be read\n");288 return -EINVAL;289 }290 291 switch (param[0]) {292 case LANE_COUNT_ONE:293 case LANE_COUNT_TWO:294 case LANE_COUNT_FOUR:295 break;296 default:297 valid_input = false;298 break;299 }300 301 switch (param[1]) {302 case LINK_RATE_LOW:303 case LINK_RATE_HIGH:304 case LINK_RATE_RBR2:305 case LINK_RATE_HIGH2:306 case LINK_RATE_HIGH3:307 case LINK_RATE_UHBR10:308 case LINK_RATE_UHBR13_5:309 case LINK_RATE_UHBR20:310 break;311 default:312 valid_input = false;313 break;314 }315 316 if (!valid_input) {317 kfree(wr_buf);318 DRM_DEBUG_DRIVER("Invalid Input value No HW will be programmed\n");319 mutex_lock(&adev->dm.dc_lock);320 dc_link_set_preferred_training_settings(dc, NULL, NULL, link, false);321 mutex_unlock(&adev->dm.dc_lock);322 return size;323 }324 325 /* save user force lane_count, link_rate to preferred settings326 * spread spectrum will not be changed327 */328 prefer_link_settings.link_spread = link->cur_link_settings.link_spread;329 prefer_link_settings.use_link_rate_set = false;330 prefer_link_settings.lane_count = param[0];331 prefer_link_settings.link_rate = param[1];332 333 mutex_lock(&adev->dm.dc_lock);334 dc_link_set_preferred_training_settings(dc, &prefer_link_settings, NULL, link, false);335 mutex_unlock(&adev->dm.dc_lock);336 337 kfree(wr_buf);338 return size;339}340 341static bool dp_mst_is_end_device(struct amdgpu_dm_connector *aconnector)342{343 bool is_end_device = false;344 struct drm_dp_mst_topology_mgr *mgr = NULL;345 struct drm_dp_mst_port *port = NULL;346 347 if (aconnector->mst_root && aconnector->mst_root->mst_mgr.mst_state) {348 mgr = &aconnector->mst_root->mst_mgr;349 port = aconnector->mst_output_port;350 351 drm_modeset_lock(&mgr->base.lock, NULL);352 if (port->pdt == DP_PEER_DEVICE_SST_SINK ||353 port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV)354 is_end_device = true;355 drm_modeset_unlock(&mgr->base.lock);356 }357 358 return is_end_device;359}360 361/* Change MST link setting362 *363 * valid lane count value: 1, 2, 4364 * valid link rate value:365 * 06h = 1.62Gbps per lane366 * 0Ah = 2.7Gbps per lane367 * 0Ch = 3.24Gbps per lane368 * 14h = 5.4Gbps per lane369 * 1Eh = 8.1Gbps per lane370 * 3E8h = 10.0Gbps per lane371 * 546h = 13.5Gbps per lane372 * 7D0h = 20.0Gbps per lane373 *374 * debugfs is located at /sys/kernel/debug/dri/0/DP-x/mst_link_settings375 *376 * for example, to force to 2 lane, 10.0GHz,377 * echo 2 0x3e8 > /sys/kernel/debug/dri/0/DP-x/mst_link_settings378 *379 * Valid input will trigger hotplug event to get new link setting applied380 * Invalid input will trigger training setting reset381 *382 * The usage can be referred to link_settings entry383 *384 */385static ssize_t dp_mst_link_setting(struct file *f, const char __user *buf,386 size_t size, loff_t *pos)387{388 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;389 struct dc_link *link = aconnector->dc_link;390 struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);391 struct dc *dc = (struct dc *)link->dc;392 struct dc_link_settings prefer_link_settings;393 char *wr_buf = NULL;394 const uint32_t wr_buf_size = 40;395 /* 0: lane_count; 1: link_rate */396 int max_param_num = 2;397 uint8_t param_nums = 0;398 long param[2];399 bool valid_input = true;400 401 if (!dp_mst_is_end_device(aconnector))402 return -EINVAL;403 404 if (size == 0)405 return -EINVAL;406 407 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);408 if (!wr_buf)409 return -ENOSPC;410 411 if (parse_write_buffer_into_params(wr_buf, wr_buf_size,412 (long *)param, buf,413 max_param_num,414 ¶m_nums)) {415 kfree(wr_buf);416 return -EINVAL;417 }418 419 if (param_nums <= 0) {420 kfree(wr_buf);421 DRM_DEBUG_DRIVER("user data not be read\n");422 return -EINVAL;423 }424 425 switch (param[0]) {426 case LANE_COUNT_ONE:427 case LANE_COUNT_TWO:428 case LANE_COUNT_FOUR:429 break;430 default:431 valid_input = false;432 break;433 }434 435 switch (param[1]) {436 case LINK_RATE_LOW:437 case LINK_RATE_HIGH:438 case LINK_RATE_RBR2:439 case LINK_RATE_HIGH2:440 case LINK_RATE_HIGH3:441 case LINK_RATE_UHBR10:442 case LINK_RATE_UHBR13_5:443 case LINK_RATE_UHBR20:444 break;445 default:446 valid_input = false;447 break;448 }449 450 if (!valid_input) {451 kfree(wr_buf);452 DRM_DEBUG_DRIVER("Invalid Input value No HW will be programmed\n");453 mutex_lock(&adev->dm.dc_lock);454 dc_link_set_preferred_training_settings(dc, NULL, NULL, link, false);455 mutex_unlock(&adev->dm.dc_lock);456 return -EINVAL;457 }458 459 /* save user force lane_count, link_rate to preferred settings460 * spread spectrum will not be changed461 */462 prefer_link_settings.link_spread = link->cur_link_settings.link_spread;463 prefer_link_settings.use_link_rate_set = false;464 prefer_link_settings.lane_count = param[0];465 prefer_link_settings.link_rate = param[1];466 467 /* skip immediate retrain, and train to new link setting after hotplug event triggered */468 mutex_lock(&adev->dm.dc_lock);469 dc_link_set_preferred_training_settings(dc, &prefer_link_settings, NULL, link, true);470 mutex_unlock(&adev->dm.dc_lock);471 472 mutex_lock(&aconnector->base.dev->mode_config.mutex);473 aconnector->base.force = DRM_FORCE_OFF;474 mutex_unlock(&aconnector->base.dev->mode_config.mutex);475 drm_kms_helper_hotplug_event(aconnector->base.dev);476 477 msleep(100);478 479 mutex_lock(&aconnector->base.dev->mode_config.mutex);480 aconnector->base.force = DRM_FORCE_UNSPECIFIED;481 mutex_unlock(&aconnector->base.dev->mode_config.mutex);482 drm_kms_helper_hotplug_event(aconnector->base.dev);483 484 kfree(wr_buf);485 return size;486}487 488/* function: get current DP PHY settings: voltage swing, pre-emphasis,489 * post-cursor2 (defined by VESA DP specification)490 *491 * valid values492 * voltage swing: 0,1,2,3493 * pre-emphasis : 0,1,2,3494 * post cursor2 : 0,1,2,3495 *496 *497 * how to use this debugfs498 *499 * debugfs is located at /sys/kernel/debug/dri/0/DP-x500 *501 * there will be directories, like DP-1, DP-2,DP-3, etc. for DP display502 *503 * To figure out which DP-x is the display for DP to be check,504 * cd DP-x505 * ls -ll506 * There should be debugfs file, like link_settings, phy_settings.507 * cat link_settings508 * from lane_count, link_rate to figure which DP-x is for display to be worked509 * on510 *511 * To get current DP PHY settings,512 * cat phy_settings513 *514 * To change DP PHY settings,515 * echo <voltage_swing> <pre-emphasis> <post_cursor2> > phy_settings516 * for examle, to change voltage swing to 2, pre-emphasis to 3, post_cursor2 to517 * 0,518 * echo 2 3 0 > phy_settings519 *520 * To check if change be applied, get current phy settings by521 * cat phy_settings522 *523 * In case invalid values are set by user, like524 * echo 1 4 0 > phy_settings525 *526 * HW will NOT be programmed by these settings.527 * cat phy_settings will show the previous valid settings.528 */529static ssize_t dp_phy_settings_read(struct file *f, char __user *buf,530 size_t size, loff_t *pos)531{532 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;533 struct dc_link *link = connector->dc_link;534 char *rd_buf = NULL;535 const uint32_t rd_buf_size = 20;536 uint32_t result = 0;537 int r;538 539 if (*pos & 3 || size & 3)540 return -EINVAL;541 542 rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);543 if (!rd_buf)544 return -EINVAL;545 546 snprintf(rd_buf, rd_buf_size, " %d %d %d\n",547 link->cur_lane_setting[0].VOLTAGE_SWING,548 link->cur_lane_setting[0].PRE_EMPHASIS,549 link->cur_lane_setting[0].POST_CURSOR2);550 551 while (size) {552 if (*pos >= rd_buf_size)553 break;554 555 r = put_user((*(rd_buf + result)), buf);556 if (r) {557 kfree(rd_buf);558 return r; /* r = -EFAULT */559 }560 561 buf += 1;562 size -= 1;563 *pos += 1;564 result += 1;565 }566 567 kfree(rd_buf);568 return result;569}570 571static int dp_lttpr_status_show(struct seq_file *m, void *unused)572{573 struct drm_connector *connector = m->private;574 struct amdgpu_dm_connector *aconnector =575 to_amdgpu_dm_connector(connector);576 struct dc_lttpr_caps caps = aconnector->dc_link->dpcd_caps.lttpr_caps;577 578 if (connector->status != connector_status_connected)579 return -ENODEV;580 581 seq_printf(m, "phy repeater count: %u (raw: 0x%x)\n",582 dp_parse_lttpr_repeater_count(caps.phy_repeater_cnt),583 caps.phy_repeater_cnt);584 585 seq_puts(m, "phy repeater mode: ");586 587 switch (caps.mode) {588 case DP_PHY_REPEATER_MODE_TRANSPARENT:589 seq_puts(m, "transparent");590 break;591 case DP_PHY_REPEATER_MODE_NON_TRANSPARENT:592 seq_puts(m, "non-transparent");593 break;594 case 0x00:595 seq_puts(m, "non lttpr");596 break;597 default:598 seq_printf(m, "read error (raw: 0x%x)", caps.mode);599 break;600 }601 602 seq_puts(m, "\n");603 return 0;604}605 606static ssize_t dp_phy_settings_write(struct file *f, const char __user *buf,607 size_t size, loff_t *pos)608{609 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;610 struct dc_link *link = connector->dc_link;611 struct dc *dc = (struct dc *)link->dc;612 char *wr_buf = NULL;613 uint32_t wr_buf_size = 40;614 long param[3];615 bool use_prefer_link_setting;616 struct link_training_settings link_lane_settings;617 int max_param_num = 3;618 uint8_t param_nums = 0;619 int r = 0;620 621 622 if (size == 0)623 return -EINVAL;624 625 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);626 if (!wr_buf)627 return -ENOSPC;628 629 if (parse_write_buffer_into_params(wr_buf, wr_buf_size,630 (long *)param, buf,631 max_param_num,632 ¶m_nums)) {633 kfree(wr_buf);634 return -EINVAL;635 }636 637 if (param_nums <= 0) {638 kfree(wr_buf);639 DRM_DEBUG_DRIVER("user data not be read\n");640 return -EINVAL;641 }642 643 if ((param[0] > VOLTAGE_SWING_MAX_LEVEL) ||644 (param[1] > PRE_EMPHASIS_MAX_LEVEL) ||645 (param[2] > POST_CURSOR2_MAX_LEVEL)) {646 kfree(wr_buf);647 DRM_DEBUG_DRIVER("Invalid Input No HW will be programmed\n");648 return size;649 }650 651 /* get link settings: lane count, link rate */652 use_prefer_link_setting =653 ((link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN) &&654 (link->test_pattern_enabled));655 656 memset(&link_lane_settings, 0, sizeof(link_lane_settings));657 658 if (use_prefer_link_setting) {659 link_lane_settings.link_settings.lane_count =660 link->preferred_link_setting.lane_count;661 link_lane_settings.link_settings.link_rate =662 link->preferred_link_setting.link_rate;663 link_lane_settings.link_settings.link_spread =664 link->preferred_link_setting.link_spread;665 } else {666 link_lane_settings.link_settings.lane_count =667 link->cur_link_settings.lane_count;668 link_lane_settings.link_settings.link_rate =669 link->cur_link_settings.link_rate;670 link_lane_settings.link_settings.link_spread =671 link->cur_link_settings.link_spread;672 }673 674 /* apply phy settings from user */675 for (r = 0; r < link_lane_settings.link_settings.lane_count; r++) {676 link_lane_settings.hw_lane_settings[r].VOLTAGE_SWING =677 (enum dc_voltage_swing) (param[0]);678 link_lane_settings.hw_lane_settings[r].PRE_EMPHASIS =679 (enum dc_pre_emphasis) (param[1]);680 link_lane_settings.hw_lane_settings[r].POST_CURSOR2 =681 (enum dc_post_cursor2) (param[2]);682 }683 684 /* program ASIC registers and DPCD registers */685 dc_link_set_drive_settings(dc, &link_lane_settings, link);686 687 kfree(wr_buf);688 return size;689}690 691/* function description692 *693 * set PHY layer or Link layer test pattern694 * PHY test pattern is used for PHY SI check.695 * Link layer test will not affect PHY SI.696 *697 * Reset Test Pattern:698 * 0 = DP_TEST_PATTERN_VIDEO_MODE699 *700 * PHY test pattern supported:701 * 1 = DP_TEST_PATTERN_D102702 * 2 = DP_TEST_PATTERN_SYMBOL_ERROR703 * 3 = DP_TEST_PATTERN_PRBS7704 * 4 = DP_TEST_PATTERN_80BIT_CUSTOM705 * 5 = DP_TEST_PATTERN_CP2520_1706 * 6 = DP_TEST_PATTERN_CP2520_2 = DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE707 * 7 = DP_TEST_PATTERN_CP2520_3708 *709 * DP PHY Link Training Patterns710 * 8 = DP_TEST_PATTERN_TRAINING_PATTERN1711 * 9 = DP_TEST_PATTERN_TRAINING_PATTERN2712 * a = DP_TEST_PATTERN_TRAINING_PATTERN3713 * b = DP_TEST_PATTERN_TRAINING_PATTERN4714 *715 * DP Link Layer Test pattern716 * c = DP_TEST_PATTERN_COLOR_SQUARES717 * d = DP_TEST_PATTERN_COLOR_SQUARES_CEA718 * e = DP_TEST_PATTERN_VERTICAL_BARS719 * f = DP_TEST_PATTERN_HORIZONTAL_BARS720 * 10= DP_TEST_PATTERN_COLOR_RAMP721 *722 * debugfs phy_test_pattern is located at /syskernel/debug/dri/0/DP-x723 *724 * --- set test pattern725 * echo <test pattern #> > test_pattern726 *727 * If test pattern # is not supported, NO HW programming will be done.728 * for DP_TEST_PATTERN_80BIT_CUSTOM, it needs extra 10 bytes of data729 * for the user pattern. input 10 bytes data are separated by space730 *731 * echo 0x4 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x99 0xaa > test_pattern732 *733 * --- reset test pattern734 * echo 0 > test_pattern735 *736 * --- HPD detection is disabled when set PHY test pattern737 *738 * when PHY test pattern (pattern # within [1,7]) is set, HPD pin of HW ASIC739 * is disable. User could unplug DP display from DP connected and plug scope to740 * check test pattern PHY SI.741 * If there is need unplug scope and plug DP display back, do steps below:742 * echo 0 > phy_test_pattern743 * unplug scope744 * plug DP display.745 *746 * "echo 0 > phy_test_pattern" will re-enable HPD pin again so that video sw747 * driver could detect "unplug scope" and "plug DP display"748 */749static ssize_t dp_phy_test_pattern_debugfs_write(struct file *f, const char __user *buf,750 size_t size, loff_t *pos)751{752 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;753 struct dc_link *link = connector->dc_link;754 char *wr_buf = NULL;755 uint32_t wr_buf_size = 100;756 long param[11] = {0x0};757 int max_param_num = 11;758 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;759 bool disable_hpd = false;760 bool valid_test_pattern = false;761 uint8_t param_nums = 0;762 /* init with default 80bit custom pattern */763 uint8_t custom_pattern[10] = {764 0x1f, 0x7c, 0xf0, 0xc1, 0x07,765 0x1f, 0x7c, 0xf0, 0xc1, 0x07766 };767 struct dc_link_settings prefer_link_settings = {LANE_COUNT_UNKNOWN,768 LINK_RATE_UNKNOWN, LINK_SPREAD_DISABLED};769 struct dc_link_settings cur_link_settings = {LANE_COUNT_UNKNOWN,770 LINK_RATE_UNKNOWN, LINK_SPREAD_DISABLED};771 struct link_training_settings link_training_settings;772 int i;773 774 if (size == 0)775 return -EINVAL;776 777 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);778 if (!wr_buf)779 return -ENOSPC;780 781 if (parse_write_buffer_into_params(wr_buf, wr_buf_size,782 (long *)param, buf,783 max_param_num,784 ¶m_nums)) {785 kfree(wr_buf);786 return -EINVAL;787 }788 789 if (param_nums <= 0) {790 kfree(wr_buf);791 DRM_DEBUG_DRIVER("user data not be read\n");792 return -EINVAL;793 }794 795 796 test_pattern = param[0];797 798 switch (test_pattern) {799 case DP_TEST_PATTERN_VIDEO_MODE:800 case DP_TEST_PATTERN_COLOR_SQUARES:801 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:802 case DP_TEST_PATTERN_VERTICAL_BARS:803 case DP_TEST_PATTERN_HORIZONTAL_BARS:804 case DP_TEST_PATTERN_COLOR_RAMP:805 valid_test_pattern = true;806 break;807 808 case DP_TEST_PATTERN_D102:809 case DP_TEST_PATTERN_SYMBOL_ERROR:810 case DP_TEST_PATTERN_PRBS7:811 case DP_TEST_PATTERN_80BIT_CUSTOM:812 case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE:813 case DP_TEST_PATTERN_TRAINING_PATTERN4:814 disable_hpd = true;815 valid_test_pattern = true;816 break;817 818 default:819 valid_test_pattern = false;820 test_pattern = DP_TEST_PATTERN_UNSUPPORTED;821 break;822 }823 824 if (!valid_test_pattern) {825 kfree(wr_buf);826 DRM_DEBUG_DRIVER("Invalid Test Pattern Parameters\n");827 return size;828 }829 830 if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) {831 for (i = 0; i < 10; i++) {832 if ((uint8_t) param[i + 1] != 0x0)833 break;834 }835 836 if (i < 10) {837 /* not use default value */838 for (i = 0; i < 10; i++)839 custom_pattern[i] = (uint8_t) param[i + 1];840 }841 }842 843 /* Usage: set DP physical test pattern using debugfs with normal DP844 * panel. Then plug out DP panel and connect a scope to measure845 * For normal video mode and test pattern generated from CRCT,846 * they are visibile to user. So do not disable HPD.847 * Video Mode is also set to clear the test pattern, so enable HPD848 * because it might have been disabled after a test pattern was set.849 * AUX depends on HPD * sequence dependent, do not move!850 */851 if (!disable_hpd)852 dc_link_enable_hpd(link);853 854 prefer_link_settings.lane_count = link->verified_link_cap.lane_count;855 prefer_link_settings.link_rate = link->verified_link_cap.link_rate;856 prefer_link_settings.link_spread = link->verified_link_cap.link_spread;857 858 cur_link_settings.lane_count = link->cur_link_settings.lane_count;859 cur_link_settings.link_rate = link->cur_link_settings.link_rate;860 cur_link_settings.link_spread = link->cur_link_settings.link_spread;861 862 link_training_settings.link_settings = cur_link_settings;863 864 865 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {866 if (prefer_link_settings.lane_count != LANE_COUNT_UNKNOWN &&867 prefer_link_settings.link_rate != LINK_RATE_UNKNOWN &&868 (prefer_link_settings.lane_count != cur_link_settings.lane_count ||869 prefer_link_settings.link_rate != cur_link_settings.link_rate))870 link_training_settings.link_settings = prefer_link_settings;871 }872 873 for (i = 0; i < (unsigned int)(link_training_settings.link_settings.lane_count); i++)874 link_training_settings.hw_lane_settings[i] = link->cur_lane_setting[i];875 876 dc_link_dp_set_test_pattern(877 link,878 test_pattern,879 DP_TEST_PATTERN_COLOR_SPACE_RGB,880 &link_training_settings,881 custom_pattern,882 10);883 884 /* Usage: Set DP physical test pattern using AMDDP with normal DP panel885 * Then plug out DP panel and connect a scope to measure DP PHY signal.886 * Need disable interrupt to avoid SW driver disable DP output. This is887 * done after the test pattern is set.888 */889 if (valid_test_pattern && disable_hpd)890 dc_link_disable_hpd(link);891 892 kfree(wr_buf);893 894 return size;895}896 897/*898 * Returns the DMCUB tracebuffer contents.899 * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_dmub_tracebuffer900 */901static int dmub_tracebuffer_show(struct seq_file *m, void *data)902{903 struct amdgpu_device *adev = m->private;904 struct dmub_srv_fb_info *fb_info = adev->dm.dmub_fb_info;905 struct dmub_debugfs_trace_entry *entries;906 uint8_t *tbuf_base;907 uint32_t tbuf_size, max_entries, num_entries, i;908 909 if (!fb_info)910 return 0;911 912 tbuf_base = (uint8_t *)fb_info->fb[DMUB_WINDOW_5_TRACEBUFF].cpu_addr;913 if (!tbuf_base)914 return 0;915 916 tbuf_size = fb_info->fb[DMUB_WINDOW_5_TRACEBUFF].size;917 max_entries = (tbuf_size - sizeof(struct dmub_debugfs_trace_header)) /918 sizeof(struct dmub_debugfs_trace_entry);919 920 num_entries =921 ((struct dmub_debugfs_trace_header *)tbuf_base)->entry_count;922 923 num_entries = min(num_entries, max_entries);924 925 entries = (struct dmub_debugfs_trace_entry926 *)(tbuf_base +927 sizeof(struct dmub_debugfs_trace_header));928 929 for (i = 0; i < num_entries; ++i) {930 struct dmub_debugfs_trace_entry *entry = &entries[i];931 932 seq_printf(m,933 "trace_code=%u tick_count=%u param0=%u param1=%u\n",934 entry->trace_code, entry->tick_count, entry->param0,935 entry->param1);936 }937 938 return 0;939}940 941/*942 * Returns the DMCUB firmware state contents.943 * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_dmub_fw_state944 */945static int dmub_fw_state_show(struct seq_file *m, void *data)946{947 struct amdgpu_device *adev = m->private;948 struct dmub_srv_fb_info *fb_info = adev->dm.dmub_fb_info;949 uint8_t *state_base;950 uint32_t state_size;951 952 if (!fb_info)953 return 0;954 955 state_base = (uint8_t *)fb_info->fb[DMUB_WINDOW_6_FW_STATE].cpu_addr;956 if (!state_base)957 return 0;958 959 state_size = fb_info->fb[DMUB_WINDOW_6_FW_STATE].size;960 961 return seq_write(m, state_base, state_size);962}963 964/* replay_capability_show() - show eDP panel replay capability965 *966 * The read function: replay_capability_show967 * Shows if sink and driver has Replay capability or not.968 *969 * cat /sys/kernel/debug/dri/0/eDP-X/replay_capability970 *971 * Expected output:972 * "Sink support: no\n" - if panel doesn't support Replay973 * "Sink support: yes\n" - if panel supports Replay974 * "Driver support: no\n" - if driver doesn't support Replay975 * "Driver support: yes\n" - if driver supports Replay976 */977static int replay_capability_show(struct seq_file *m, void *data)978{979 struct drm_connector *connector = m->private;980 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);981 struct dc_link *link = aconnector->dc_link;982 bool sink_support_replay = false;983 bool driver_support_replay = false;984 985 if (!link)986 return -ENODEV;987 988 if (link->type == dc_connection_none)989 return -ENODEV;990 991 if (!(link->connector_signal & SIGNAL_TYPE_EDP))992 return -ENODEV;993 994 /* If Replay is already set to support, skip the checks */995 if (link->replay_settings.config.replay_supported) {996 sink_support_replay = true;997 driver_support_replay = true;998 } else if ((amdgpu_dc_debug_mask & DC_DISABLE_REPLAY)) {999 sink_support_replay = amdgpu_dm_link_supports_replay(link, aconnector);1000 } else {1001 struct dc *dc = link->ctx->dc;1002 1003 sink_support_replay = amdgpu_dm_link_supports_replay(link, aconnector);1004 if (dc->ctx->dmub_srv && dc->ctx->dmub_srv->dmub)1005 driver_support_replay =1006 (bool)dc->ctx->dmub_srv->dmub->feature_caps.replay_supported;1007 }1008 1009 seq_printf(m, "Sink support: %s\n", str_yes_no(sink_support_replay));1010 seq_printf(m, "Driver support: %s\n", str_yes_no(driver_support_replay));1011 seq_printf(m, "Config support: %s\n", str_yes_no(link->replay_settings.config.replay_supported));1012 1013 return 0;1014}1015 1016/* psr_capability_show() - show eDP panel PSR capability1017 *1018 * The read function: sink_psr_capability_show1019 * Shows if sink has PSR capability or not.1020 * If yes - the PSR version is appended1021 *1022 * cat /sys/kernel/debug/dri/0/eDP-X/psr_capability1023 *1024 * Expected output:1025 * "Sink support: no\n" - if panel doesn't support PSR1026 * "Sink support: yes [0x01]\n" - if panel supports PSR11027 * "Driver support: no\n" - if driver doesn't support PSR1028 * "Driver support: yes [0x01]\n" - if driver supports PSR11029 */1030static int psr_capability_show(struct seq_file *m, void *data)1031{1032 struct drm_connector *connector = m->private;1033 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);1034 struct dc_link *link = aconnector->dc_link;1035 1036 if (!link)1037 return -ENODEV;1038 1039 if (link->type == dc_connection_none)1040 return -ENODEV;1041 1042 if (!(link->connector_signal & SIGNAL_TYPE_EDP))1043 return -ENODEV;1044 1045 seq_printf(m, "Sink support: %s", str_yes_no(link->dpcd_caps.psr_info.psr_version != 0));1046 if (link->dpcd_caps.psr_info.psr_version)1047 seq_printf(m, " [0x%02x]", link->dpcd_caps.psr_info.psr_version);1048 seq_puts(m, "\n");1049 1050 seq_printf(m, "Driver support: %s", str_yes_no(link->psr_settings.psr_feature_enabled));1051 if (link->psr_settings.psr_version)1052 seq_printf(m, " [0x%02x]", link->psr_settings.psr_version);1053 seq_puts(m, "\n");1054 1055 return 0;1056}1057 1058/*1059 * Returns the current bpc for the crtc.1060 * Example usage: cat /sys/kernel/debug/dri/0/crtc-0/amdgpu_current_bpc1061 */1062static int amdgpu_current_bpc_show(struct seq_file *m, void *data)1063{1064 struct drm_crtc *crtc = m->private;1065 struct drm_device *dev = crtc->dev;1066 struct dm_crtc_state *dm_crtc_state = NULL;1067 int res = -ENODEV;1068 unsigned int bpc;1069 1070 mutex_lock(&dev->mode_config.mutex);1071 drm_modeset_lock(&crtc->mutex, NULL);1072 if (crtc->state == NULL)1073 goto unlock;1074 1075 dm_crtc_state = to_dm_crtc_state(crtc->state);1076 if (dm_crtc_state->stream == NULL)1077 goto unlock;1078 1079 switch (dm_crtc_state->stream->timing.display_color_depth) {1080 case COLOR_DEPTH_666:1081 bpc = 6;1082 break;1083 case COLOR_DEPTH_888:1084 bpc = 8;1085 break;1086 case COLOR_DEPTH_101010:1087 bpc = 10;1088 break;1089 case COLOR_DEPTH_121212:1090 bpc = 12;1091 break;1092 case COLOR_DEPTH_161616:1093 bpc = 16;1094 break;1095 default:1096 goto unlock;1097 }1098 1099 seq_printf(m, "Current: %u\n", bpc);1100 res = 0;1101 1102unlock:1103 drm_modeset_unlock(&crtc->mutex);1104 mutex_unlock(&dev->mode_config.mutex);1105 1106 return res;1107}1108DEFINE_SHOW_ATTRIBUTE(amdgpu_current_bpc);1109 1110/*1111 * Returns the current colorspace for the crtc.1112 * Example usage: cat /sys/kernel/debug/dri/0/crtc-0/amdgpu_current_colorspace1113 */1114static int amdgpu_current_colorspace_show(struct seq_file *m, void *data)1115{1116 struct drm_crtc *crtc = m->private;1117 struct drm_device *dev = crtc->dev;1118 struct dm_crtc_state *dm_crtc_state = NULL;1119 int res = -ENODEV;1120 1121 mutex_lock(&dev->mode_config.mutex);1122 drm_modeset_lock(&crtc->mutex, NULL);1123 if (crtc->state == NULL)1124 goto unlock;1125 1126 dm_crtc_state = to_dm_crtc_state(crtc->state);1127 if (dm_crtc_state->stream == NULL)1128 goto unlock;1129 1130 switch (dm_crtc_state->stream->output_color_space) {1131 case COLOR_SPACE_SRGB:1132 seq_puts(m, "sRGB");1133 break;1134 case COLOR_SPACE_YCBCR601:1135 case COLOR_SPACE_YCBCR601_LIMITED:1136 seq_puts(m, "BT601_YCC");1137 break;1138 case COLOR_SPACE_YCBCR709:1139 case COLOR_SPACE_YCBCR709_LIMITED:1140 seq_puts(m, "BT709_YCC");1141 break;1142 case COLOR_SPACE_ADOBERGB:1143 seq_puts(m, "opRGB");1144 break;1145 case COLOR_SPACE_2020_RGB_FULLRANGE:1146 seq_puts(m, "BT2020_RGB");1147 break;1148 case COLOR_SPACE_2020_YCBCR:1149 seq_puts(m, "BT2020_YCC");1150 break;1151 default:1152 goto unlock;1153 }1154 res = 0;1155 1156unlock:1157 drm_modeset_unlock(&crtc->mutex);1158 mutex_unlock(&dev->mode_config.mutex);1159 1160 return res;1161}1162DEFINE_SHOW_ATTRIBUTE(amdgpu_current_colorspace);1163 1164 1165/*1166 * Example usage:1167 * Disable dsc passthrough, i.e.,: have dsc decoding at converver, not external RX1168 * echo 1 /sys/kernel/debug/dri/0/DP-1/dsc_disable_passthrough1169 * Enable dsc passthrough, i.e.,: have dsc passthrough to external RX1170 * echo 0 /sys/kernel/debug/dri/0/DP-1/dsc_disable_passthrough1171 */1172static ssize_t dp_dsc_passthrough_set(struct file *f, const char __user *buf,1173 size_t size, loff_t *pos)1174{1175 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;1176 char *wr_buf = NULL;1177 uint32_t wr_buf_size = 42;1178 int max_param_num = 1;1179 long param;1180 uint8_t param_nums = 0;1181 1182 if (size == 0)1183 return -EINVAL;1184 1185 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);1186 1187 if (!wr_buf) {1188 DRM_DEBUG_DRIVER("no memory to allocate write buffer\n");1189 return -ENOSPC;1190 }1191 1192 if (parse_write_buffer_into_params(wr_buf, wr_buf_size,1193 ¶m, buf,1194 max_param_num,1195 ¶m_nums)) {1196 kfree(wr_buf);1197 return -EINVAL;1198 }1199 1200 aconnector->dsc_settings.dsc_force_disable_passthrough = param;1201 1202 kfree(wr_buf);1203 return 0;1204}1205 1206/*1207 * Returns the HDCP capability of the Display (1.4 for now).1208 *1209 * NOTE* Not all HDMI displays report their HDCP caps even when they are capable.1210 * Since its rare for a display to not be HDCP 1.4 capable, we set HDMI as always capable.1211 *1212 * Example usage: cat /sys/kernel/debug/dri/0/DP-1/hdcp_sink_capability1213 * or cat /sys/kernel/debug/dri/0/HDMI-A-1/hdcp_sink_capability1214 */1215static int hdcp_sink_capability_show(struct seq_file *m, void *data)1216{1217 struct drm_connector *connector = m->private;1218 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);1219 bool hdcp_cap, hdcp2_cap;1220 1221 if (connector->status != connector_status_connected)1222 return -ENODEV;1223 1224 seq_printf(m, "%s:%d HDCP version: ", connector->name, connector->base.id);1225 1226 hdcp_cap = dc_link_is_hdcp14(aconnector->dc_link, aconnector->dc_sink->sink_signal);1227 hdcp2_cap = dc_link_is_hdcp22(aconnector->dc_link, aconnector->dc_sink->sink_signal);1228 1229 1230 if (hdcp_cap)1231 seq_printf(m, "%s ", "HDCP1.4");1232 if (hdcp2_cap)1233 seq_printf(m, "%s ", "HDCP2.2");1234 1235 if (!hdcp_cap && !hdcp2_cap)1236 seq_printf(m, "%s ", "None");1237 1238 seq_puts(m, "\n");1239 1240 return 0;1241}1242 1243/*1244 * Returns whether the connected display is internal and not hotpluggable.1245 * Example usage: cat /sys/kernel/debug/dri/0/DP-1/internal_display1246 */1247static int internal_display_show(struct seq_file *m, void *data)1248{1249 struct drm_connector *connector = m->private;1250 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);1251 struct dc_link *link = aconnector->dc_link;1252 1253 seq_printf(m, "Internal: %u\n", link->is_internal_display);1254 1255 return 0;1256}1257 1258/*1259 * Returns the number of segments used if ODM Combine mode is enabled.1260 * Example usage: cat /sys/kernel/debug/dri/0/DP-1/odm_combine_segments1261 */1262static int odm_combine_segments_show(struct seq_file *m, void *unused)1263{1264 struct drm_connector *connector = m->private;1265 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);1266 struct dc_link *link = aconnector->dc_link;1267 struct pipe_ctx *pipe_ctx = NULL;1268 int i, segments = -EOPNOTSUPP;1269 1270 for (i = 0; i < MAX_PIPES; i++) {1271 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];1272 if (pipe_ctx->stream &&1273 pipe_ctx->stream->link == link)1274 break;1275 }1276 1277 if (connector->status != connector_status_connected)1278 return -ENODEV;1279 1280 if (pipe_ctx != NULL && pipe_ctx->stream_res.tg->funcs->get_odm_combine_segments)1281 pipe_ctx->stream_res.tg->funcs->get_odm_combine_segments(pipe_ctx->stream_res.tg, &segments);1282 1283 seq_printf(m, "%d\n", segments);1284 return 0;1285}1286 1287/* function description1288 *1289 * generic SDP message access for testing1290 *1291 * debugfs sdp_message is located at /syskernel/debug/dri/0/DP-x1292 *1293 * SDP header1294 * Hb0 : Secondary-Data Packet ID1295 * Hb1 : Secondary-Data Packet type1296 * Hb2 : Secondary-Data-packet-specific header, Byte 01297 * Hb3 : Secondary-Data-packet-specific header, Byte 11298 *1299 * for using custom sdp message: input 4 bytes SDP header and 32 bytes raw data1300 */1301static ssize_t dp_sdp_message_debugfs_write(struct file *f, const char __user *buf,1302 size_t size, loff_t *pos)1303{1304 int r;1305 uint8_t data[36] = {0};1306 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;1307 struct dm_crtc_state *acrtc_state;1308 uint32_t write_size = 36;1309 1310 if (connector->base.status != connector_status_connected)1311 return -ENODEV;1312 1313 if (size == 0)1314 return 0;1315 1316 acrtc_state = to_dm_crtc_state(connector->base.state->crtc->state);1317 1318 r = copy_from_user(data, buf, write_size);1319 1320 write_size -= r;1321 1322 dc_stream_send_dp_sdp(acrtc_state->stream, data, write_size);1323 1324 return write_size;1325}1326 1327/* function: Read link's DSC & FEC capabilities1328 *1329 *1330 * Access it with the following command (you need to specify1331 * connector like DP-1):1332 *1333 * cat /sys/kernel/debug/dri/0/DP-X/dp_dsc_fec_support1334 *1335 */1336static int dp_dsc_fec_support_show(struct seq_file *m, void *data)1337{1338 struct drm_connector *connector = m->private;1339 struct drm_modeset_acquire_ctx ctx;1340 struct drm_device *dev = connector->dev;1341 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);1342 int ret = 0;1343 bool try_again = false;1344 bool is_fec_supported = false;1345 bool is_dsc_supported = false;1346 struct dpcd_caps dpcd_caps;1347 1348 drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);1349 do {1350 try_again = false;1351 ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);1352 if (ret) {1353 if (ret == -EDEADLK) {1354 ret = drm_modeset_backoff(&ctx);1355 if (!ret) {1356 try_again = true;1357 continue;1358 }1359 }1360 break;1361 }1362 if (connector->status != connector_status_connected) {1363 ret = -ENODEV;1364 break;1365 }1366 dpcd_caps = aconnector->dc_link->dpcd_caps;1367 if (aconnector->mst_output_port) {1368 /* aconnector sets dsc_aux during get_modes call1369 * if MST connector has it means it can either1370 * enable DSC on the sink device or on MST branch1371 * its connected to.1372 */1373 if (aconnector->dsc_aux) {1374 is_fec_supported = true;1375 is_dsc_supported = true;1376 }1377 } else {1378 is_fec_supported = dpcd_caps.fec_cap.raw & 0x1;1379 is_dsc_supported = dpcd_caps.dsc_caps.dsc_basic_caps.raw[0] & 0x1;1380 }1381 } while (try_again);1382 1383 drm_modeset_drop_locks(&ctx);1384 drm_modeset_acquire_fini(&ctx);1385 1386 seq_printf(m, "FEC_Sink_Support: %s\n", str_yes_no(is_fec_supported));1387 seq_printf(m, "DSC_Sink_Support: %s\n", str_yes_no(is_dsc_supported));1388 1389 return ret;1390}1391 1392/* function: Trigger virtual HPD redetection on connector1393 *1394 * This function will perform link rediscovery, link disable1395 * and enable, and dm connector state update.1396 *1397 * Retrigger HPD on an existing connector by echoing 1 into1398 * its respectful "trigger_hotplug" debugfs entry:1399 *1400 * echo 1 > /sys/kernel/debug/dri/0/DP-X/trigger_hotplug1401 *1402 * This function can perform HPD unplug:1403 *1404 * echo 0 > /sys/kernel/debug/dri/0/DP-X/trigger_hotplug1405 *1406 */1407static ssize_t trigger_hotplug(struct file *f, const char __user *buf,1408 size_t size, loff_t *pos)1409{1410 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;1411 struct drm_connector *connector = &aconnector->base;1412 struct dc_link *link = NULL;1413 struct drm_device *dev = connector->dev;1414 struct amdgpu_device *adev = drm_to_adev(dev);1415 enum dc_connection_type new_connection_type = dc_connection_none;1416 char *wr_buf = NULL;1417 uint32_t wr_buf_size = 42;1418 int max_param_num = 1;1419 long param[1] = {0};1420 uint8_t param_nums = 0;1421 bool ret = false;1422 1423 if (!aconnector->dc_link)1424 return -EINVAL;1425 1426 if (size == 0)1427 return -EINVAL;1428 1429 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);1430 1431 if (!wr_buf) {1432 DRM_DEBUG_DRIVER("no memory to allocate write buffer\n");1433 return -ENOSPC;1434 }1435 1436 if (parse_write_buffer_into_params(wr_buf, wr_buf_size,1437 (long *)param, buf,1438 max_param_num,1439 ¶m_nums)) {1440 kfree(wr_buf);1441 return -EINVAL;1442 }1443 1444 kfree(wr_buf);1445 1446 if (param_nums <= 0) {1447 DRM_DEBUG_DRIVER("user data not be read\n");1448 return -EINVAL;1449 }1450 1451 mutex_lock(&aconnector->hpd_lock);1452 1453 /* Don't support for mst end device*/1454 if (aconnector->mst_root) {1455 mutex_unlock(&aconnector->hpd_lock);1456 return -EINVAL;1457 }1458 1459 if (param[0] == 1) {1460 1461 if (!dc_link_detect_connection_type(aconnector->dc_link, &new_connection_type) &&1462 new_connection_type != dc_connection_none)1463 goto unlock;1464 1465 mutex_lock(&adev->dm.dc_lock);1466 ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);1467 mutex_unlock(&adev->dm.dc_lock);1468 1469 if (!ret)1470 goto unlock;1471 1472 amdgpu_dm_update_connector_after_detect(aconnector);1473 1474 drm_modeset_lock_all(dev);1475 dm_restore_drm_connector_state(dev, connector);1476 drm_modeset_unlock_all(dev);1477 1478 drm_kms_helper_connector_hotplug_event(connector);1479 } else if (param[0] == 0) {1480 if (!aconnector->dc_link)1481 goto unlock;1482 1483 link = aconnector->dc_link;1484 1485 if (link->local_sink) {1486 dc_sink_release(link->local_sink);1487 link->local_sink = NULL;1488 }1489 1490 link->dpcd_sink_count = 0;1491 link->type = dc_connection_none;1492 link->dongle_max_pix_clk = 0;1493 1494 amdgpu_dm_update_connector_after_detect(aconnector);1495 1496 /* If the aconnector is the root node in mst topology */1497 if (aconnector->mst_mgr.mst_state == true)1498 dc_link_reset_cur_dp_mst_topology(link);1499 1500 drm_modeset_lock_all(dev);1501 dm_restore_drm_connector_state(dev, connector);1502 drm_modeset_unlock_all(dev);1503 1504 drm_kms_helper_connector_hotplug_event(connector);1505 }1506 1507unlock:1508 mutex_unlock(&aconnector->hpd_lock);1509 1510 return size;1511}1512 1513/* function: read DSC status on the connector1514 *1515 * The read function: dp_dsc_clock_en_read1516 * returns current status of DSC clock on the connector.1517 * The return is a boolean flag: 1 or 0.1518 *1519 * Access it with the following command (you need to specify1520 * connector like DP-1):1521 *1522 * cat /sys/kernel/debug/dri/0/DP-X/dsc_clock_en1523 *1524 * Expected output:1525 * 1 - means that DSC is currently enabled1526 * 0 - means that DSC is disabled1527 */1528static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,1529 size_t size, loff_t *pos)1530{1531 char *rd_buf = NULL;1532 char *rd_buf_ptr = NULL;1533 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;1534 struct display_stream_compressor *dsc;1535 struct dcn_dsc_state dsc_state = {0};1536 const uint32_t rd_buf_size = 10;1537 struct pipe_ctx *pipe_ctx;1538 ssize_t result = 0;1539 int i, r, str_len = 10;1540 1541 rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);1542 1543 if (!rd_buf)1544 return -ENOMEM;1545 1546 rd_buf_ptr = rd_buf;1547 1548 for (i = 0; i < MAX_PIPES; i++) {1549 pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];1550 if (pipe_ctx->stream &&1551 pipe_ctx->stream->link == aconnector->dc_link &&1552 pipe_ctx->stream->sink &&1553 pipe_ctx->stream->sink == aconnector->dc_sink)1554 break;1555 }1556 1557 dsc = pipe_ctx->stream_res.dsc;1558 if (dsc)1559 dsc->funcs->dsc_read_state(dsc, &dsc_state);1560 1561 snprintf(rd_buf_ptr, str_len,1562 "%d\n",1563 dsc_state.dsc_clock_en);1564 rd_buf_ptr += str_len;1565 1566 while (size) {1567 if (*pos >= rd_buf_size)1568 break;1569 1570 r = put_user(*(rd_buf + result), buf);1571 if (r) {1572 kfree(rd_buf);1573 return r; /* r = -EFAULT */1574 }1575 1576 buf += 1;1577 size -= 1;1578 *pos += 1;1579 result += 1;1580 }1581 1582 kfree(rd_buf);1583 return result;1584}1585 1586/* function: write force DSC on the connector1587 *1588 * The write function: dp_dsc_clock_en_write1589 * enables to force DSC on the connector.1590 * User can write to either force enable or force disable DSC1591 * on the next modeset or set it to driver default1592 *1593 * Accepted inputs:1594 * 0 - default DSC enablement policy1595 * 1 - force enable DSC on the connector1596 * 2 - force disable DSC on the connector (might cause fail in atomic_check)1597 *1598 * Writing DSC settings is done with the following command:1599 * - To force enable DSC (you need to specify1600 * connector like DP-1):1601 *1602 * echo 0x1 > /sys/kernel/debug/dri/0/DP-X/dsc_clock_en1603 *1604 * - To return to default state set the flag to zero and1605 * let driver deal with DSC automatically1606 * (you need to specify connector like DP-1):1607 *1608 * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_clock_en1609 *1610 */1611static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf,1612 size_t size, loff_t *pos)1613{1614 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;1615 struct drm_connector *connector = &aconnector->base;1616 struct drm_device *dev = connector->dev;1617 struct drm_crtc *crtc = NULL;1618 struct dm_crtc_state *dm_crtc_state = NULL;1619 struct pipe_ctx *pipe_ctx;1620 int i;1621 char *wr_buf = NULL;1622 uint32_t wr_buf_size = 42;1623 int max_param_num = 1;1624 long param[1] = {0};1625 uint8_t param_nums = 0;1626 1627 if (size == 0)1628 return -EINVAL;1629 1630 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);1631 1632 if (!wr_buf) {1633 DRM_DEBUG_DRIVER("no memory to allocate write buffer\n");1634 return -ENOSPC;1635 }1636 1637 if (parse_write_buffer_into_params(wr_buf, wr_buf_size,1638 (long *)param, buf,1639 max_param_num,1640 ¶m_nums)) {1641 kfree(wr_buf);1642 return -EINVAL;1643 }1644 1645 if (param_nums <= 0) {1646 DRM_DEBUG_DRIVER("user data not be read\n");1647 kfree(wr_buf);1648 return -EINVAL;1649 }1650 1651 for (i = 0; i < MAX_PIPES; i++) {1652 pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];1653 if (pipe_ctx->stream &&1654 pipe_ctx->stream->link == aconnector->dc_link &&1655 pipe_ctx->stream->sink &&1656 pipe_ctx->stream->sink == aconnector->dc_sink)1657 break;1658 }1659 1660 if (!pipe_ctx->stream)1661 goto done;1662 1663 // Get CRTC state1664 mutex_lock(&dev->mode_config.mutex);1665 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);1666 1667 if (connector->state == NULL)1668 goto unlock;1669 1670 crtc = connector->state->crtc;1671 if (crtc == NULL)1672 goto unlock;1673 1674 drm_modeset_lock(&crtc->mutex, NULL);1675 if (crtc->state == NULL)1676 goto unlock;1677 1678 dm_crtc_state = to_dm_crtc_state(crtc->state);1679 if (dm_crtc_state->stream == NULL)1680 goto unlock;1681 1682 if (param[0] == 1)1683 aconnector->dsc_settings.dsc_force_enable = DSC_CLK_FORCE_ENABLE;1684 else if (param[0] == 2)1685 aconnector->dsc_settings.dsc_force_enable = DSC_CLK_FORCE_DISABLE;1686 else1687 aconnector->dsc_settings.dsc_force_enable = DSC_CLK_FORCE_DEFAULT;1688 1689 dm_crtc_state->dsc_force_changed = true;1690 1691unlock:1692 if (crtc)1693 drm_modeset_unlock(&crtc->mutex);1694 drm_modeset_unlock(&dev->mode_config.connection_mutex);1695 mutex_unlock(&dev->mode_config.mutex);1696 1697done:1698 kfree(wr_buf);1699 return size;1700}1701 1702/* function: read DSC slice width parameter on the connector1703 *1704 * The read function: dp_dsc_slice_width_read1705 * returns dsc slice width used in the current configuration1706 * The return is an integer: 0 or other positive number1707 *1708 * Access the status with the following command:1709 *1710 * cat /sys/kernel/debug/dri/0/DP-X/dsc_slice_width1711 *1712 * 0 - means that DSC is disabled1713 *1714 * Any other number more than zero represents the1715 * slice width currently used by DSC in pixels1716 *1717 */1718static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,1719 size_t size, loff_t *pos)1720{1721 char *rd_buf = NULL;1722 char *rd_buf_ptr = NULL;1723 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;1724 struct display_stream_compressor *dsc;1725 struct dcn_dsc_state dsc_state = {0};1726 const uint32_t rd_buf_size = 100;1727 struct pipe_ctx *pipe_ctx;1728 ssize_t result = 0;1729 int i, r, str_len = 30;1730 1731 rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);1732 1733 if (!rd_buf)1734 return -ENOMEM;1735 1736 rd_buf_ptr = rd_buf;1737 1738 for (i = 0; i < MAX_PIPES; i++) {1739 pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];1740 if (pipe_ctx->stream &&1741 pipe_ctx->stream->link == aconnector->dc_link &&1742 pipe_ctx->stream->sink &&1743 pipe_ctx->stream->sink == aconnector->dc_sink)1744 break;1745 }1746 1747 dsc = pipe_ctx->stream_res.dsc;1748 if (dsc)1749 dsc->funcs->dsc_read_state(dsc, &dsc_state);1750 1751 snprintf(rd_buf_ptr, str_len,1752 "%d\n",1753 dsc_state.dsc_slice_width);1754 rd_buf_ptr += str_len;1755 1756 while (size) {1757 if (*pos >= rd_buf_size)1758 break;1759 1760 r = put_user(*(rd_buf + result), buf);1761 if (r) {1762 kfree(rd_buf);1763 return r; /* r = -EFAULT */1764 }1765 1766 buf += 1;1767 size -= 1;1768 *pos += 1;1769 result += 1;1770 }1771 1772 kfree(rd_buf);1773 return result;1774}1775 1776/* function: write DSC slice width parameter1777 *1778 * The write function: dp_dsc_slice_width_write1779 * overwrites automatically generated DSC configuration1780 * of slice width.1781 *1782 * The user has to write the slice width divisible by the1783 * picture width.1784 *1785 * Also the user has to write width in hexidecimal1786 * rather than in decimal.1787 *1788 * Writing DSC settings is done with the following command:1789 * - To force overwrite slice width: (example sets to 1920 pixels)1790 *1791 * echo 0x780 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_width1792 *1793 * - To stop overwriting and let driver find the optimal size,1794 * set the width to zero:1795 *1796 * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_width1797 *1798 */1799static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf,1800 size_t size, loff_t *pos)1801{1802 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;1803 struct pipe_ctx *pipe_ctx;1804 struct drm_connector *connector = &aconnector->base;1805 struct drm_device *dev = connector->dev;1806 struct drm_crtc *crtc = NULL;1807 struct dm_crtc_state *dm_crtc_state = NULL;1808 int i;1809 char *wr_buf = NULL;1810 uint32_t wr_buf_size = 42;1811 int max_param_num = 1;1812 long param[1] = {0};1813 uint8_t param_nums = 0;1814 1815 if (size == 0)1816 return -EINVAL;1817 1818 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);1819 1820 if (!wr_buf) {1821 DRM_DEBUG_DRIVER("no memory to allocate write buffer\n");1822 return -ENOSPC;1823 }1824 1825 if (parse_write_buffer_into_params(wr_buf, wr_buf_size,1826 (long *)param, buf,1827 max_param_num,1828 ¶m_nums)) {1829 kfree(wr_buf);1830 return -EINVAL;1831 }1832 1833 if (param_nums <= 0) {1834 DRM_DEBUG_DRIVER("user data not be read\n");1835 kfree(wr_buf);1836 return -EINVAL;1837 }1838 1839 for (i = 0; i < MAX_PIPES; i++) {1840 pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];1841 if (pipe_ctx->stream &&1842 pipe_ctx->stream->link == aconnector->dc_link &&1843 pipe_ctx->stream->sink &&1844 pipe_ctx->stream->sink == aconnector->dc_sink)1845 break;1846 }1847 1848 if (!pipe_ctx->stream)1849 goto done;1850 1851 // Safely get CRTC state1852 mutex_lock(&dev->mode_config.mutex);1853 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);1854 1855 if (connector->state == NULL)1856 goto unlock;1857 1858 crtc = connector->state->crtc;1859 if (crtc == NULL)1860 goto unlock;1861 1862 drm_modeset_lock(&crtc->mutex, NULL);1863 if (crtc->state == NULL)1864 goto unlock;1865 1866 dm_crtc_state = to_dm_crtc_state(crtc->state);1867 if (dm_crtc_state->stream == NULL)1868 goto unlock;1869 1870 if (param[0] > 0)1871 aconnector->dsc_settings.dsc_num_slices_h = DIV_ROUND_UP(1872 pipe_ctx->stream->timing.h_addressable,1873 param[0]);1874 else1875 aconnector->dsc_settings.dsc_num_slices_h = 0;1876 1877 dm_crtc_state->dsc_force_changed = true;1878 1879unlock:1880 if (crtc)1881 drm_modeset_unlock(&crtc->mutex);1882 drm_modeset_unlock(&dev->mode_config.connection_mutex);1883 mutex_unlock(&dev->mode_config.mutex);1884 1885done:1886 kfree(wr_buf);1887 return size;1888}1889 1890/* function: read DSC slice height parameter on the connector1891 *1892 * The read function: dp_dsc_slice_height_read1893 * returns dsc slice height used in the current configuration1894 * The return is an integer: 0 or other positive number1895 *1896 * Access the status with the following command:1897 *1898 * cat /sys/kernel/debug/dri/0/DP-X/dsc_slice_height1899 *1900 * 0 - means that DSC is disabled1901 *1902 * Any other number more than zero represents the1903 * slice height currently used by DSC in pixels1904 *1905 */1906static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,1907 size_t size, loff_t *pos)1908{1909 char *rd_buf = NULL;1910 char *rd_buf_ptr = NULL;1911 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;1912 struct display_stream_compressor *dsc;1913 struct dcn_dsc_state dsc_state = {0};1914 const uint32_t rd_buf_size = 100;1915 struct pipe_ctx *pipe_ctx;1916 ssize_t result = 0;1917 int i, r, str_len = 30;1918 1919 rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);1920 1921 if (!rd_buf)1922 return -ENOMEM;1923 1924 rd_buf_ptr = rd_buf;1925 1926 for (i = 0; i < MAX_PIPES; i++) {1927 pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];1928 if (pipe_ctx->stream &&1929 pipe_ctx->stream->link == aconnector->dc_link &&1930 pipe_ctx->stream->sink &&1931 pipe_ctx->stream->sink == aconnector->dc_sink)1932 break;1933 }1934 1935 dsc = pipe_ctx->stream_res.dsc;1936 if (dsc)1937 dsc->funcs->dsc_read_state(dsc, &dsc_state);1938 1939 snprintf(rd_buf_ptr, str_len,1940 "%d\n",1941 dsc_state.dsc_slice_height);1942 rd_buf_ptr += str_len;1943 1944 while (size) {1945 if (*pos >= rd_buf_size)1946 break;1947 1948 r = put_user(*(rd_buf + result), buf);1949 if (r) {1950 kfree(rd_buf);1951 return r; /* r = -EFAULT */1952 }1953 1954 buf += 1;1955 size -= 1;1956 *pos += 1;1957 result += 1;1958 }1959 1960 kfree(rd_buf);1961 return result;1962}1963 1964/* function: write DSC slice height parameter1965 *1966 * The write function: dp_dsc_slice_height_write1967 * overwrites automatically generated DSC configuration1968 * of slice height.1969 *1970 * The user has to write the slice height divisible by the1971 * picture height.1972 *1973 * Also the user has to write height in hexidecimal1974 * rather than in decimal.1975 *1976 * Writing DSC settings is done with the following command:1977 * - To force overwrite slice height (example sets to 128 pixels):1978 *1979 * echo 0x80 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_height1980 *1981 * - To stop overwriting and let driver find the optimal size,1982 * set the height to zero:1983 *1984 * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_height1985 *1986 */1987static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf,1988 size_t size, loff_t *pos)1989{1990 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;1991 struct drm_connector *connector = &aconnector->base;1992 struct drm_device *dev = connector->dev;1993 struct drm_crtc *crtc = NULL;1994 struct dm_crtc_state *dm_crtc_state = NULL;1995 struct pipe_ctx *pipe_ctx;1996 int i;1997 char *wr_buf = NULL;1998 uint32_t wr_buf_size = 42;1999 int max_param_num = 1;2000 uint8_t param_nums = 0;2001 long param[1] = {0};2002 2003 if (size == 0)2004 return -EINVAL;2005 2006 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);2007 2008 if (!wr_buf) {2009 DRM_DEBUG_DRIVER("no memory to allocate write buffer\n");2010 return -ENOSPC;2011 }2012 2013 if (parse_write_buffer_into_params(wr_buf, wr_buf_size,2014 (long *)param, buf,2015 max_param_num,2016 ¶m_nums)) {2017 kfree(wr_buf);2018 return -EINVAL;2019 }2020 2021 if (param_nums <= 0) {2022 DRM_DEBUG_DRIVER("user data not be read\n");2023 kfree(wr_buf);2024 return -EINVAL;2025 }2026 2027 for (i = 0; i < MAX_PIPES; i++) {2028 pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];2029 if (pipe_ctx->stream &&2030 pipe_ctx->stream->link == aconnector->dc_link &&2031 pipe_ctx->stream->sink &&2032 pipe_ctx->stream->sink == aconnector->dc_sink)2033 break;2034 }2035 2036 if (!pipe_ctx->stream)2037 goto done;2038 2039 // Get CRTC state2040 mutex_lock(&dev->mode_config.mutex);2041 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);2042 2043 if (connector->state == NULL)2044 goto unlock;2045 2046 crtc = connector->state->crtc;2047 if (crtc == NULL)2048 goto unlock;2049 2050 drm_modeset_lock(&crtc->mutex, NULL);2051 if (crtc->state == NULL)2052 goto unlock;2053 2054 dm_crtc_state = to_dm_crtc_state(crtc->state);2055 if (dm_crtc_state->stream == NULL)2056 goto unlock;2057 2058 if (param[0] > 0)2059 aconnector->dsc_settings.dsc_num_slices_v = DIV_ROUND_UP(2060 pipe_ctx->stream->timing.v_addressable,2061 param[0]);2062 else2063 aconnector->dsc_settings.dsc_num_slices_v = 0;2064 2065 dm_crtc_state->dsc_force_changed = true;2066 2067unlock:2068 if (crtc)2069 drm_modeset_unlock(&crtc->mutex);2070 drm_modeset_unlock(&dev->mode_config.connection_mutex);2071 mutex_unlock(&dev->mode_config.mutex);2072 2073done:2074 kfree(wr_buf);2075 return size;2076}2077 2078/* function: read DSC target rate on the connector in bits per pixel2079 *2080 * The read function: dp_dsc_bits_per_pixel_read2081 * returns target rate of compression in bits per pixel2082 * The return is an integer: 0 or other positive integer2083 *2084 * Access it with the following command:2085 *2086 * cat /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel2087 *2088 * 0 - means that DSC is disabled2089 */2090static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,2091 size_t size, loff_t *pos)2092{2093 char *rd_buf = NULL;2094 char *rd_buf_ptr = NULL;2095 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;2096 struct display_stream_compressor *dsc;2097 struct dcn_dsc_state dsc_state = {0};2098 const uint32_t rd_buf_size = 100;2099 struct pipe_ctx *pipe_ctx;2100 ssize_t result = 0;2101 int i, r, str_len = 30;2102 2103 rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);2104 2105 if (!rd_buf)2106 return -ENOMEM;2107 2108 rd_buf_ptr = rd_buf;2109 2110 for (i = 0; i < MAX_PIPES; i++) {2111 pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];2112 if (pipe_ctx->stream &&2113 pipe_ctx->stream->link == aconnector->dc_link &&2114 pipe_ctx->stream->sink &&2115 pipe_ctx->stream->sink == aconnector->dc_sink)2116 break;2117 }2118 2119 dsc = pipe_ctx->stream_res.dsc;2120 if (dsc)2121 dsc->funcs->dsc_read_state(dsc, &dsc_state);2122 2123 snprintf(rd_buf_ptr, str_len,2124 "%d\n",2125 dsc_state.dsc_bits_per_pixel);2126 rd_buf_ptr += str_len;2127 2128 while (size) {2129 if (*pos >= rd_buf_size)2130 break;2131 2132 r = put_user(*(rd_buf + result), buf);2133 if (r) {2134 kfree(rd_buf);2135 return r; /* r = -EFAULT */2136 }2137 2138 buf += 1;2139 size -= 1;2140 *pos += 1;2141 result += 1;2142 }2143 2144 kfree(rd_buf);2145 return result;2146}2147 2148/* function: write DSC target rate in bits per pixel2149 *2150 * The write function: dp_dsc_bits_per_pixel_write2151 * overwrites automatically generated DSC configuration2152 * of DSC target bit rate.2153 *2154 * Also the user has to write bpp in hexidecimal2155 * rather than in decimal.2156 *2157 * Writing DSC settings is done with the following command:2158 * - To force overwrite rate (example sets to 256 bpp x 1/16):2159 *2160 * echo 0x100 > /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel2161 *2162 * - To stop overwriting and let driver find the optimal rate,2163 * set the rate to zero:2164 *2165 * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel2166 *2167 */2168static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *buf,2169 size_t size, loff_t *pos)2170{2171 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;2172 struct drm_connector *connector = &aconnector->base;2173 struct drm_device *dev = connector->dev;2174 struct drm_crtc *crtc = NULL;2175 struct dm_crtc_state *dm_crtc_state = NULL;2176 struct pipe_ctx *pipe_ctx;2177 int i;2178 char *wr_buf = NULL;2179 uint32_t wr_buf_size = 42;2180 int max_param_num = 1;2181 uint8_t param_nums = 0;2182 long param[1] = {0};2183 2184 if (size == 0)2185 return -EINVAL;2186 2187 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);2188 2189 if (!wr_buf) {2190 DRM_DEBUG_DRIVER("no memory to allocate write buffer\n");2191 return -ENOSPC;2192 }2193 2194 if (parse_write_buffer_into_params(wr_buf, wr_buf_size,2195 (long *)param, buf,2196 max_param_num,2197 ¶m_nums)) {2198 kfree(wr_buf);2199 return -EINVAL;2200 }2201 2202 if (param_nums <= 0) {2203 DRM_DEBUG_DRIVER("user data not be read\n");2204 kfree(wr_buf);2205 return -EINVAL;2206 }2207 2208 for (i = 0; i < MAX_PIPES; i++) {2209 pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];2210 if (pipe_ctx->stream &&2211 pipe_ctx->stream->link == aconnector->dc_link &&2212 pipe_ctx->stream->sink &&2213 pipe_ctx->stream->sink == aconnector->dc_sink)2214 break;2215 }2216 2217 if (!pipe_ctx->stream)2218 goto done;2219 2220 // Get CRTC state2221 mutex_lock(&dev->mode_config.mutex);2222 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);2223 2224 if (connector->state == NULL)2225 goto unlock;2226 2227 crtc = connector->state->crtc;2228 if (crtc == NULL)2229 goto unlock;2230 2231 drm_modeset_lock(&crtc->mutex, NULL);2232 if (crtc->state == NULL)2233 goto unlock;2234 2235 dm_crtc_state = to_dm_crtc_state(crtc->state);2236 if (dm_crtc_state->stream == NULL)2237 goto unlock;2238 2239 aconnector->dsc_settings.dsc_bits_per_pixel = param[0];2240 2241 dm_crtc_state->dsc_force_changed = true;2242 2243unlock:2244 if (crtc)2245 drm_modeset_unlock(&crtc->mutex);2246 drm_modeset_unlock(&dev->mode_config.connection_mutex);2247 mutex_unlock(&dev->mode_config.mutex);2248 2249done:2250 kfree(wr_buf);2251 return size;2252}2253 2254/* function: read DSC picture width parameter on the connector2255 *2256 * The read function: dp_dsc_pic_width_read2257 * returns dsc picture width used in the current configuration2258 * It is the same as h_addressable of the current2259 * display's timing2260 * The return is an integer: 0 or other positive integer2261 * If 0 then DSC is disabled.2262 *2263 * Access it with the following command:2264 *2265 * cat /sys/kernel/debug/dri/0/DP-X/dsc_pic_width2266 *2267 * 0 - means that DSC is disabled2268 */2269static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,2270 size_t size, loff_t *pos)2271{2272 char *rd_buf = NULL;2273 char *rd_buf_ptr = NULL;2274 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;2275 struct display_stream_compressor *dsc;2276 struct dcn_dsc_state dsc_state = {0};2277 const uint32_t rd_buf_size = 100;2278 struct pipe_ctx *pipe_ctx;2279 ssize_t result = 0;2280 int i, r, str_len = 30;2281 2282 rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);2283 2284 if (!rd_buf)2285 return -ENOMEM;2286 2287 rd_buf_ptr = rd_buf;2288 2289 for (i = 0; i < MAX_PIPES; i++) {2290 pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];2291 if (pipe_ctx->stream &&2292 pipe_ctx->stream->link == aconnector->dc_link &&2293 pipe_ctx->stream->sink &&2294 pipe_ctx->stream->sink == aconnector->dc_sink)2295 break;2296 }2297 2298 dsc = pipe_ctx->stream_res.dsc;2299 if (dsc)2300 dsc->funcs->dsc_read_state(dsc, &dsc_state);2301 2302 snprintf(rd_buf_ptr, str_len,2303 "%d\n",2304 dsc_state.dsc_pic_width);2305 rd_buf_ptr += str_len;2306 2307 while (size) {2308 if (*pos >= rd_buf_size)2309 break;2310 2311 r = put_user(*(rd_buf + result), buf);2312 if (r) {2313 kfree(rd_buf);2314 return r; /* r = -EFAULT */2315 }2316 2317 buf += 1;2318 size -= 1;2319 *pos += 1;2320 result += 1;2321 }2322 2323 kfree(rd_buf);2324 return result;2325}2326 2327static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,2328 size_t size, loff_t *pos)2329{2330 char *rd_buf = NULL;2331 char *rd_buf_ptr = NULL;2332 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;2333 struct display_stream_compressor *dsc;2334 struct dcn_dsc_state dsc_state = {0};2335 const uint32_t rd_buf_size = 100;2336 struct pipe_ctx *pipe_ctx;2337 ssize_t result = 0;2338 int i, r, str_len = 30;2339 2340 rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);2341 2342 if (!rd_buf)2343 return -ENOMEM;2344 2345 rd_buf_ptr = rd_buf;2346 2347 for (i = 0; i < MAX_PIPES; i++) {2348 pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];2349 if (pipe_ctx->stream &&2350 pipe_ctx->stream->link == aconnector->dc_link &&2351 pipe_ctx->stream->sink &&2352 pipe_ctx->stream->sink == aconnector->dc_sink)2353 break;2354 }2355 2356 dsc = pipe_ctx->stream_res.dsc;2357 if (dsc)2358 dsc->funcs->dsc_read_state(dsc, &dsc_state);2359 2360 snprintf(rd_buf_ptr, str_len,2361 "%d\n",2362 dsc_state.dsc_pic_height);2363 rd_buf_ptr += str_len;2364 2365 while (size) {2366 if (*pos >= rd_buf_size)2367 break;2368 2369 r = put_user(*(rd_buf + result), buf);2370 if (r) {2371 kfree(rd_buf);2372 return r; /* r = -EFAULT */2373 }2374 2375 buf += 1;2376 size -= 1;2377 *pos += 1;2378 result += 1;2379 }2380 2381 kfree(rd_buf);2382 return result;2383}2384 2385/* function: read DSC chunk size parameter on the connector2386 *2387 * The read function: dp_dsc_chunk_size_read2388 * returns dsc chunk size set in the current configuration2389 * The value is calculated automatically by DSC code2390 * and depends on slice parameters and bpp target rate2391 * The return is an integer: 0 or other positive integer2392 * If 0 then DSC is disabled.2393 *2394 * Access it with the following command:2395 *2396 * cat /sys/kernel/debug/dri/0/DP-X/dsc_chunk_size2397 *2398 * 0 - means that DSC is disabled2399 */2400static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,2401 size_t size, loff_t *pos)2402{2403 char *rd_buf = NULL;2404 char *rd_buf_ptr = NULL;2405 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;2406 struct display_stream_compressor *dsc;2407 struct dcn_dsc_state dsc_state = {0};2408 const uint32_t rd_buf_size = 100;2409 struct pipe_ctx *pipe_ctx;2410 ssize_t result = 0;2411 int i, r, str_len = 30;2412 2413 rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);2414 2415 if (!rd_buf)2416 return -ENOMEM;2417 2418 rd_buf_ptr = rd_buf;2419 2420 for (i = 0; i < MAX_PIPES; i++) {2421 pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];2422 if (pipe_ctx->stream &&2423 pipe_ctx->stream->link == aconnector->dc_link &&2424 pipe_ctx->stream->sink &&2425 pipe_ctx->stream->sink == aconnector->dc_sink)2426 break;2427 }2428 2429 dsc = pipe_ctx->stream_res.dsc;2430 if (dsc)2431 dsc->funcs->dsc_read_state(dsc, &dsc_state);2432 2433 snprintf(rd_buf_ptr, str_len,2434 "%d\n",2435 dsc_state.dsc_chunk_size);2436 rd_buf_ptr += str_len;2437 2438 while (size) {2439 if (*pos >= rd_buf_size)2440 break;2441 2442 r = put_user(*(rd_buf + result), buf);2443 if (r) {2444 kfree(rd_buf);2445 return r; /* r = -EFAULT */2446 }2447 2448 buf += 1;2449 size -= 1;2450 *pos += 1;2451 result += 1;2452 }2453 2454 kfree(rd_buf);2455 return result;2456}2457 2458/* function: read DSC slice bpg offset on the connector2459 *2460 * The read function: dp_dsc_slice_bpg_offset_read2461 * returns dsc bpg slice offset set in the current configuration2462 * The value is calculated automatically by DSC code2463 * and depends on slice parameters and bpp target rate2464 * The return is an integer: 0 or other positive integer2465 * If 0 then DSC is disabled.2466 *2467 * Access it with the following command:2468 *2469 * cat /sys/kernel/debug/dri/0/DP-X/dsc_slice_bpg_offset2470 *2471 * 0 - means that DSC is disabled2472 */2473static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,2474 size_t size, loff_t *pos)2475{2476 char *rd_buf = NULL;2477 char *rd_buf_ptr = NULL;2478 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;2479 struct display_stream_compressor *dsc;2480 struct dcn_dsc_state dsc_state = {0};2481 const uint32_t rd_buf_size = 100;2482 struct pipe_ctx *pipe_ctx;2483 ssize_t result = 0;2484 int i, r, str_len = 30;2485 2486 rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);2487 2488 if (!rd_buf)2489 return -ENOMEM;2490 2491 rd_buf_ptr = rd_buf;2492 2493 for (i = 0; i < MAX_PIPES; i++) {2494 pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];2495 if (pipe_ctx->stream &&2496 pipe_ctx->stream->link == aconnector->dc_link &&2497 pipe_ctx->stream->sink &&2498 pipe_ctx->stream->sink == aconnector->dc_sink)2499 break;2500 }2501 2502 dsc = pipe_ctx->stream_res.dsc;2503 if (dsc)2504 dsc->funcs->dsc_read_state(dsc, &dsc_state);2505 2506 snprintf(rd_buf_ptr, str_len,2507 "%d\n",2508 dsc_state.dsc_slice_bpg_offset);2509 rd_buf_ptr += str_len;2510 2511 while (size) {2512 if (*pos >= rd_buf_size)2513 break;2514 2515 r = put_user(*(rd_buf + result), buf);2516 if (r) {2517 kfree(rd_buf);2518 return r; /* r = -EFAULT */2519 }2520 2521 buf += 1;2522 size -= 1;2523 *pos += 1;2524 result += 1;2525 }2526 2527 kfree(rd_buf);2528 return result;2529}2530 2531 2532/*2533 * function description: Read max_requested_bpc property from the connector2534 *2535 * Access it with the following command:2536 *2537 * cat /sys/kernel/debug/dri/0/DP-X/max_bpc2538 *2539 */2540static ssize_t dp_max_bpc_read(struct file *f, char __user *buf,2541 size_t size, loff_t *pos)2542{2543 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;2544 struct drm_connector *connector = &aconnector->base;2545 struct drm_device *dev = connector->dev;2546 struct dm_connector_state *state;2547 ssize_t result = 0;2548 char *rd_buf = NULL;2549 char *rd_buf_ptr = NULL;2550 const uint32_t rd_buf_size = 10;2551 int r;2552 2553 rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);2554 2555 if (!rd_buf)2556 return -ENOMEM;2557 2558 mutex_lock(&dev->mode_config.mutex);2559 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);2560 2561 if (connector->state == NULL)2562 goto unlock;2563 2564 state = to_dm_connector_state(connector->state);2565 2566 rd_buf_ptr = rd_buf;2567 snprintf(rd_buf_ptr, rd_buf_size,2568 "%u\n",2569 state->base.max_requested_bpc);2570 2571 while (size) {2572 if (*pos >= rd_buf_size)2573 break;2574 2575 r = put_user(*(rd_buf + result), buf);2576 if (r) {2577 result = r; /* r = -EFAULT */2578 goto unlock;2579 }2580 buf += 1;2581 size -= 1;2582 *pos += 1;2583 result += 1;2584 }2585unlock:2586 drm_modeset_unlock(&dev->mode_config.connection_mutex);2587 mutex_unlock(&dev->mode_config.mutex);2588 kfree(rd_buf);2589 return result;2590}2591 2592 2593/*2594 * function description: Set max_requested_bpc property on the connector2595 *2596 * This function will not force the input BPC on connector, it will only2597 * change the max value. This is equivalent to setting max_bpc through2598 * xrandr.2599 *2600 * The BPC value written must be >= 6 and <= 16. Values outside of this2601 * range will result in errors.2602 *2603 * BPC values:2604 * 0x6 - 6 BPC2605 * 0x8 - 8 BPC2606 * 0xa - 10 BPC2607 * 0xc - 12 BPC2608 * 0x10 - 16 BPC2609 *2610 * Write the max_bpc in the following way:2611 *2612 * echo 0x6 > /sys/kernel/debug/dri/0/DP-X/max_bpc2613 *2614 */2615static ssize_t dp_max_bpc_write(struct file *f, const char __user *buf,2616 size_t size, loff_t *pos)2617{2618 struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;2619 struct drm_connector *connector = &aconnector->base;2620 struct dm_connector_state *state;2621 struct drm_device *dev = connector->dev;2622 char *wr_buf = NULL;2623 uint32_t wr_buf_size = 42;2624 int max_param_num = 1;2625 long param[1] = {0};2626 uint8_t param_nums = 0;2627 2628 if (size == 0)2629 return -EINVAL;2630 2631 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);2632 2633 if (!wr_buf) {2634 DRM_DEBUG_DRIVER("no memory to allocate write buffer\n");2635 return -ENOSPC;2636 }2637 2638 if (parse_write_buffer_into_params(wr_buf, wr_buf_size,2639 (long *)param, buf,2640 max_param_num,2641 ¶m_nums)) {2642 kfree(wr_buf);2643 return -EINVAL;2644 }2645 2646 if (param_nums <= 0) {2647 DRM_DEBUG_DRIVER("user data not be read\n");2648 kfree(wr_buf);2649 return -EINVAL;2650 }2651 2652 if (param[0] < 6 || param[0] > 16) {2653 DRM_DEBUG_DRIVER("bad max_bpc value\n");2654 kfree(wr_buf);2655 return -EINVAL;2656 }2657 2658 mutex_lock(&dev->mode_config.mutex);2659 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);2660 2661 if (connector->state == NULL)2662 goto unlock;2663 2664 state = to_dm_connector_state(connector->state);2665 state->base.max_requested_bpc = param[0];2666unlock:2667 drm_modeset_unlock(&dev->mode_config.connection_mutex);2668 mutex_unlock(&dev->mode_config.mutex);2669 2670 kfree(wr_buf);2671 return size;2672}2673 2674/*2675 * IPS status. Read only.2676 *2677 * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_ips_status2678 */2679static int ips_status_show(struct seq_file *m, void *unused)2680{2681 struct amdgpu_device *adev = m->private;2682 struct dc *dc = adev->dm.dc;2683 struct dc_dmub_srv *dc_dmub_srv;2684 2685 seq_printf(m, "IPS config: %d\n", dc->config.disable_ips);2686 seq_printf(m, "Idle optimization: %d\n", dc->idle_optimizations_allowed);2687 2688 if (adev->dm.idle_workqueue) {2689 seq_printf(m, "Idle workqueue - enabled: %d\n", adev->dm.idle_workqueue->enable);2690 seq_printf(m, "Idle workqueue - running: %d\n", adev->dm.idle_workqueue->running);2691 }2692 2693 dc_dmub_srv = dc->ctx->dmub_srv;2694 if (dc_dmub_srv && dc_dmub_srv->dmub) {2695 uint32_t rcg_count, ips1_count, ips2_count;2696 volatile const struct dmub_shared_state_ips_fw *ips_fw =2697 &dc_dmub_srv->dmub->shared_state[DMUB_SHARED_SHARE_FEATURE__IPS_FW].data.ips_fw;2698 rcg_count = ips_fw->rcg_entry_count;2699 ips1_count = ips_fw->ips1_entry_count;2700 ips2_count = ips_fw->ips2_entry_count;2701 seq_printf(m, "entry counts: rcg=%u ips1=%u ips2=%u\n",2702 rcg_count,2703 ips1_count,2704 ips2_count);2705 rcg_count = ips_fw->rcg_exit_count;2706 ips1_count = ips_fw->ips1_exit_count;2707 ips2_count = ips_fw->ips2_exit_count;2708 seq_printf(m, "exit counts: rcg=%u ips1=%u ips2=%u",2709 rcg_count,2710 ips1_count,2711 ips2_count);2712 seq_puts(m, "\n");2713 }2714 return 0;2715}2716 2717/*2718 * Backlight at this moment. Read only.2719 * As written to display, taking ABM and backlight lut into account.2720 * Ranges from 0x0 to 0x10000 (= 100% PWM)2721 *2722 * Example usage: cat /sys/kernel/debug/dri/0/eDP-1/current_backlight2723 */2724static int current_backlight_show(struct seq_file *m, void *unused)2725{2726 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(m->private);2727 struct dc_link *link = aconnector->dc_link;2728 unsigned int backlight;2729 2730 backlight = dc_link_get_backlight_level(link);2731 seq_printf(m, "0x%x\n", backlight);2732 2733 return 0;2734}2735 2736/*2737 * Backlight value that is being approached. Read only.2738 * As written to display, taking ABM and backlight lut into account.2739 * Ranges from 0x0 to 0x10000 (= 100% PWM)2740 *2741 * Example usage: cat /sys/kernel/debug/dri/0/eDP-1/target_backlight2742 */2743static int target_backlight_show(struct seq_file *m, void *unused)2744{2745 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(m->private);2746 struct dc_link *link = aconnector->dc_link;2747 unsigned int backlight;2748 2749 backlight = dc_link_get_target_backlight_pwm(link);2750 seq_printf(m, "0x%x\n", backlight);2751 2752 return 0;2753}2754 2755/*2756 * function description: Determine if the connector is mst connector2757 *2758 * This function helps to determine whether a connector is a mst connector.2759 * - "root" stands for the root connector of the topology2760 * - "branch" stands for branch device of the topology2761 * - "end" stands for leaf node connector of the topology2762 * - "no" stands for the connector is not a device of a mst topology2763 * Access it with the following command:2764 *2765 * cat /sys/kernel/debug/dri/0/DP-X/is_mst_connector2766 *2767 */2768static int dp_is_mst_connector_show(struct seq_file *m, void *unused)2769{2770 struct drm_connector *connector = m->private;2771 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);2772 struct drm_dp_mst_topology_mgr *mgr = NULL;2773 struct drm_dp_mst_port *port = NULL;2774 char *role = NULL;2775 2776 mutex_lock(&aconnector->hpd_lock);2777 2778 if (aconnector->mst_mgr.mst_state) {2779 role = "root";2780 } else if (aconnector->mst_root &&2781 aconnector->mst_root->mst_mgr.mst_state) {2782 2783 role = "end";2784 2785 mgr = &aconnector->mst_root->mst_mgr;2786 port = aconnector->mst_output_port;2787 2788 drm_modeset_lock(&mgr->base.lock, NULL);2789 if (port->pdt == DP_PEER_DEVICE_MST_BRANCHING &&2790 port->mcs)2791 role = "branch";2792 drm_modeset_unlock(&mgr->base.lock);2793 2794 } else {2795 role = "no";2796 }2797 2798 seq_printf(m, "%s\n", role);2799 2800 mutex_unlock(&aconnector->hpd_lock);2801 2802 return 0;2803}2804 2805/*2806 * function description: Read out the mst progress status2807 *2808 * This function helps to determine the mst progress status of2809 * a mst connector.2810 *2811 * Access it with the following command:2812 *2813 * cat /sys/kernel/debug/dri/0/DP-X/mst_progress_status2814 *2815 */2816static int dp_mst_progress_status_show(struct seq_file *m, void *unused)2817{2818 struct drm_connector *connector = m->private;2819 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);2820 struct amdgpu_device *adev = drm_to_adev(connector->dev);2821 int i;2822 2823 mutex_lock(&aconnector->hpd_lock);2824 mutex_lock(&adev->dm.dc_lock);2825 2826 if (aconnector->mst_status == MST_STATUS_DEFAULT) {2827 seq_puts(m, "disabled\n");2828 } else {2829 for (i = 0; i < sizeof(mst_progress_status)/sizeof(char *); i++)2830 seq_printf(m, "%s:%s\n",2831 mst_progress_status[i],2832 aconnector->mst_status & BIT(i) ? "done" : "not_done");2833 }2834 2835 mutex_unlock(&adev->dm.dc_lock);2836 mutex_unlock(&aconnector->hpd_lock);2837 2838 return 0;2839}2840 2841/*2842 * Reports whether the connected display is a USB4 DPIA tunneled display2843 * Example usage: cat /sys/kernel/debug/dri/0/DP-8/is_dpia_link2844 */2845static int is_dpia_link_show(struct seq_file *m, void *data)2846{2847 struct drm_connector *connector = m->private;2848 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);2849 struct dc_link *link = aconnector->dc_link;2850 2851 if (connector->status != connector_status_connected)2852 return -ENODEV;2853 2854 seq_printf(m, "%s\n", (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) ? "yes" :2855 (link->ep_type == DISPLAY_ENDPOINT_PHY) ? "no" : "unknown");2856 2857 return 0;2858}2859 2860DEFINE_SHOW_ATTRIBUTE(dp_dsc_fec_support);2861DEFINE_SHOW_ATTRIBUTE(dmub_fw_state);2862DEFINE_SHOW_ATTRIBUTE(dmub_tracebuffer);2863DEFINE_SHOW_ATTRIBUTE(dp_lttpr_status);2864DEFINE_SHOW_ATTRIBUTE(hdcp_sink_capability);2865DEFINE_SHOW_ATTRIBUTE(internal_display);2866DEFINE_SHOW_ATTRIBUTE(odm_combine_segments);2867DEFINE_SHOW_ATTRIBUTE(replay_capability);2868DEFINE_SHOW_ATTRIBUTE(psr_capability);2869DEFINE_SHOW_ATTRIBUTE(dp_is_mst_connector);2870DEFINE_SHOW_ATTRIBUTE(dp_mst_progress_status);2871DEFINE_SHOW_ATTRIBUTE(is_dpia_link);2872 2873static const struct file_operations dp_dsc_clock_en_debugfs_fops = {2874 .owner = THIS_MODULE,2875 .read = dp_dsc_clock_en_read,2876 .write = dp_dsc_clock_en_write,2877 .llseek = default_llseek2878};2879 2880static const struct file_operations dp_dsc_slice_width_debugfs_fops = {2881 .owner = THIS_MODULE,2882 .read = dp_dsc_slice_width_read,2883 .write = dp_dsc_slice_width_write,2884 .llseek = default_llseek2885};2886 2887static const struct file_operations dp_dsc_slice_height_debugfs_fops = {2888 .owner = THIS_MODULE,2889 .read = dp_dsc_slice_height_read,2890 .write = dp_dsc_slice_height_write,2891 .llseek = default_llseek2892};2893 2894static const struct file_operations dp_dsc_bits_per_pixel_debugfs_fops = {2895 .owner = THIS_MODULE,2896 .read = dp_dsc_bits_per_pixel_read,2897 .write = dp_dsc_bits_per_pixel_write,2898 .llseek = default_llseek2899};2900 2901static const struct file_operations dp_dsc_pic_width_debugfs_fops = {2902 .owner = THIS_MODULE,2903 .read = dp_dsc_pic_width_read,2904 .llseek = default_llseek2905};2906 2907static const struct file_operations dp_dsc_pic_height_debugfs_fops = {2908 .owner = THIS_MODULE,2909 .read = dp_dsc_pic_height_read,2910 .llseek = default_llseek2911};2912 2913static const struct file_operations dp_dsc_chunk_size_debugfs_fops = {2914 .owner = THIS_MODULE,2915 .read = dp_dsc_chunk_size_read,2916 .llseek = default_llseek2917};2918 2919static const struct file_operations dp_dsc_slice_bpg_offset_debugfs_fops = {2920 .owner = THIS_MODULE,2921 .read = dp_dsc_slice_bpg_offset_read,2922 .llseek = default_llseek2923};2924 2925static const struct file_operations trigger_hotplug_debugfs_fops = {2926 .owner = THIS_MODULE,2927 .write = trigger_hotplug,2928 .llseek = default_llseek2929};2930 2931static const struct file_operations dp_link_settings_debugfs_fops = {2932 .owner = THIS_MODULE,2933 .read = dp_link_settings_read,2934 .write = dp_link_settings_write,2935 .llseek = default_llseek2936};2937 2938static const struct file_operations dp_phy_settings_debugfs_fop = {2939 .owner = THIS_MODULE,2940 .read = dp_phy_settings_read,2941 .write = dp_phy_settings_write,2942 .llseek = default_llseek2943};2944 2945static const struct file_operations dp_phy_test_pattern_fops = {2946 .owner = THIS_MODULE,2947 .write = dp_phy_test_pattern_debugfs_write,2948 .llseek = default_llseek2949};2950 2951static const struct file_operations sdp_message_fops = {2952 .owner = THIS_MODULE,2953 .write = dp_sdp_message_debugfs_write,2954 .llseek = default_llseek2955};2956 2957static const struct file_operations dp_max_bpc_debugfs_fops = {2958 .owner = THIS_MODULE,2959 .read = dp_max_bpc_read,2960 .write = dp_max_bpc_write,2961 .llseek = default_llseek2962};2963 2964static const struct file_operations dp_dsc_disable_passthrough_debugfs_fops = {2965 .owner = THIS_MODULE,2966 .write = dp_dsc_passthrough_set,2967 .llseek = default_llseek2968};2969 2970static const struct file_operations dp_mst_link_settings_debugfs_fops = {2971 .owner = THIS_MODULE,2972 .write = dp_mst_link_setting,2973 .llseek = default_llseek2974};2975 2976static const struct {2977 char *name;2978 const struct file_operations *fops;2979} dp_debugfs_entries[] = {2980 {"link_settings", &dp_link_settings_debugfs_fops},2981 {"phy_settings", &dp_phy_settings_debugfs_fop},2982 {"lttpr_status", &dp_lttpr_status_fops},2983 {"test_pattern", &dp_phy_test_pattern_fops},2984 {"hdcp_sink_capability", &hdcp_sink_capability_fops},2985 {"sdp_message", &sdp_message_fops},2986 {"dsc_clock_en", &dp_dsc_clock_en_debugfs_fops},2987 {"dsc_slice_width", &dp_dsc_slice_width_debugfs_fops},2988 {"dsc_slice_height", &dp_dsc_slice_height_debugfs_fops},2989 {"dsc_bits_per_pixel", &dp_dsc_bits_per_pixel_debugfs_fops},2990 {"dsc_pic_width", &dp_dsc_pic_width_debugfs_fops},2991 {"dsc_pic_height", &dp_dsc_pic_height_debugfs_fops},2992 {"dsc_chunk_size", &dp_dsc_chunk_size_debugfs_fops},2993 {"dsc_slice_bpg", &dp_dsc_slice_bpg_offset_debugfs_fops},2994 {"dp_dsc_fec_support", &dp_dsc_fec_support_fops},2995 {"max_bpc", &dp_max_bpc_debugfs_fops},2996 {"dsc_disable_passthrough", &dp_dsc_disable_passthrough_debugfs_fops},2997 {"is_mst_connector", &dp_is_mst_connector_fops},2998 {"mst_progress_status", &dp_mst_progress_status_fops},2999 {"is_dpia_link", &is_dpia_link_fops},3000 {"mst_link_settings", &dp_mst_link_settings_debugfs_fops}3001};3002 3003static const struct {3004 char *name;3005 const struct file_operations *fops;3006} hdmi_debugfs_entries[] = {3007 {"hdcp_sink_capability", &hdcp_sink_capability_fops}3008};3009 3010/*3011 * Force YUV420 output if available from the given mode3012 */3013static int force_yuv420_output_set(void *data, u64 val)3014{3015 struct amdgpu_dm_connector *connector = data;3016 3017 connector->force_yuv420_output = (bool)val;3018 3019 return 0;3020}3021 3022/*3023 * Check if YUV420 is forced when available from the given mode3024 */3025static int force_yuv420_output_get(void *data, u64 *val)3026{3027 struct amdgpu_dm_connector *connector = data;3028 3029 *val = connector->force_yuv420_output;3030 3031 return 0;3032}3033 3034DEFINE_DEBUGFS_ATTRIBUTE(force_yuv420_output_fops, force_yuv420_output_get,3035 force_yuv420_output_set, "%llu\n");3036 3037/*3038 * Read Replay state3039 */3040static int replay_get_state(void *data, u64 *val)3041{3042 struct amdgpu_dm_connector *connector = data;3043 struct dc_link *link = connector->dc_link;3044 uint64_t state = REPLAY_STATE_INVALID;3045 3046 dc_link_get_replay_state(link, &state);3047 3048 *val = state;3049 3050 return 0;3051}3052 3053/*3054 * Read PSR state3055 */3056static int psr_get(void *data, u64 *val)3057{3058 struct amdgpu_dm_connector *connector = data;3059 struct dc_link *link = connector->dc_link;3060 enum dc_psr_state state = PSR_STATE0;3061 3062 dc_link_get_psr_state(link, &state);3063 3064 *val = state;3065 3066 return 0;3067}3068 3069/*3070 * Read PSR state residency3071 */3072static int psr_read_residency(void *data, u64 *val)3073{3074 struct amdgpu_dm_connector *connector = data;3075 struct dc_link *link = connector->dc_link;3076 u32 residency = 0;3077 3078 link->dc->link_srv->edp_get_psr_residency(link, &residency, PSR_RESIDENCY_MODE_PHY);3079 3080 *val = (u64)residency;3081 3082 return 0;3083}3084 3085/* read allow_edp_hotplug_detection */3086static int allow_edp_hotplug_detection_get(void *data, u64 *val)3087{3088 struct amdgpu_dm_connector *aconnector = data;3089 struct drm_connector *connector = &aconnector->base;3090 struct drm_device *dev = connector->dev;3091 struct amdgpu_device *adev = drm_to_adev(dev);3092 3093 *val = adev->dm.dc->config.allow_edp_hotplug_detection;3094 3095 return 0;3096}3097 3098/* set allow_edp_hotplug_detection */3099static int allow_edp_hotplug_detection_set(void *data, u64 val)3100{3101 struct amdgpu_dm_connector *aconnector = data;3102 struct drm_connector *connector = &aconnector->base;3103 struct drm_device *dev = connector->dev;3104 struct amdgpu_device *adev = drm_to_adev(dev);3105 3106 adev->dm.dc->config.allow_edp_hotplug_detection = (uint32_t) val;3107 3108 return 0;3109}3110 3111/* check if kernel disallow eDP enter psr state3112 * cat /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_psr3113 * 0: allow edp enter psr; 1: disallow3114 */3115static int disallow_edp_enter_psr_get(void *data, u64 *val)3116{3117 struct amdgpu_dm_connector *aconnector = data;3118 3119 *val = (u64) aconnector->disallow_edp_enter_psr;3120 return 0;3121}3122 3123/* set kernel disallow eDP enter psr state3124 * echo 0x0 /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_psr3125 * 0: allow edp enter psr; 1: disallow3126 *3127 * usage: test app read crc from PSR eDP rx.3128 *3129 * during kernel boot up, kernel write dpcd 0x170 = 5.3130 * this notify eDP rx psr enable and let rx check crc.3131 * rx fw will start checking crc for rx internal logic.3132 * crc read count within dpcd 0x246 is not updated and3133 * value is 0. when eDP tx driver wants to read rx crc3134 * from dpcd 0x246, 0x270, read count 0 lead tx driver3135 * timeout.3136 *3137 * to avoid this, we add this debugfs to let test app to disbable3138 * rx crc checking for rx internal logic. then test app can read3139 * non-zero crc read count.3140 *3141 * expected app sequence is as below:3142 * 1. disable eDP PHY and notify eDP rx with dpcd 0x600 = 2.3143 * 2. echo 0x1 /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_psr3144 * 3. enable eDP PHY and notify eDP rx with dpcd 0x600 = 1 but3145 * without dpcd 0x170 = 5.3146 * 4. read crc from rx dpcd 0x270, 0x246, etc.3147 * 5. echo 0x0 /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_psr.3148 * this will let eDP back to normal with psr setup dpcd 0x170 = 5.3149 */3150static int disallow_edp_enter_psr_set(void *data, u64 val)3151{3152 struct amdgpu_dm_connector *aconnector = data;3153 3154 aconnector->disallow_edp_enter_psr = val ? true : false;3155 return 0;3156}3157 3158static int dmub_trace_mask_set(void *data, u64 val)3159{3160 struct amdgpu_device *adev = data;3161 struct dmub_srv *srv = adev->dm.dc->ctx->dmub_srv->dmub;3162 enum dmub_gpint_command cmd;3163 u64 mask = 0xffff;3164 u8 shift = 0;3165 u32 res;3166 int i;3167 3168 if (!srv->fw_version)3169 return -EINVAL;3170 3171 for (i = 0; i < 4; i++) {3172 res = (val & mask) >> shift;3173 3174 switch (i) {3175 case 0:3176 cmd = DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD0;3177 break;3178 case 1:3179 cmd = DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD1;3180 break;3181 case 2:3182 cmd = DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD2;3183 break;3184 case 3:3185 cmd = DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD3;3186 break;3187 }3188 3189 if (!dc_wake_and_execute_gpint(adev->dm.dc->ctx, cmd, res, NULL, DM_DMUB_WAIT_TYPE_WAIT))3190 return -EIO;3191 3192 usleep_range(100, 1000);3193 3194 mask <<= 16;3195 shift += 16;3196 }3197 3198 return 0;3199}3200 3201static int dmub_trace_mask_show(void *data, u64 *val)3202{3203 enum dmub_gpint_command cmd = DMUB_GPINT__GET_TRACE_BUFFER_MASK_WORD0;3204 struct amdgpu_device *adev = data;3205 struct dmub_srv *srv = adev->dm.dc->ctx->dmub_srv->dmub;3206 u8 shift = 0;3207 u64 raw = 0;3208 u64 res = 0;3209 int i = 0;3210 3211 if (!srv->fw_version)3212 return -EINVAL;3213 3214 while (i < 4) {3215 uint32_t response;3216 3217 if (!dc_wake_and_execute_gpint(adev->dm.dc->ctx, cmd, 0, &response, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))3218 return -EIO;3219 3220 raw = response;3221 usleep_range(100, 1000);3222 3223 cmd++;3224 res |= (raw << shift);3225 shift += 16;3226 i++;3227 }3228 3229 *val = res;3230 3231 return 0;3232}3233 3234DEFINE_DEBUGFS_ATTRIBUTE(dmub_trace_mask_fops, dmub_trace_mask_show,3235 dmub_trace_mask_set, "0x%llx\n");3236 3237/*3238 * Set dmcub trace event IRQ enable or disable.3239 * Usage to enable dmcub trace event IRQ: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dmcub_trace_event_en3240 * Usage to disable dmcub trace event IRQ: echo 0 > /sys/kernel/debug/dri/0/amdgpu_dm_dmcub_trace_event_en3241 */3242static int dmcub_trace_event_state_set(void *data, u64 val)3243{3244 struct amdgpu_device *adev = data;3245 3246 if (val == 1 || val == 0) {3247 dc_dmub_trace_event_control(adev->dm.dc, val);3248 adev->dm.dmcub_trace_event_en = (bool)val;3249 } else3250 return 0;3251 3252 return 0;3253}3254 3255/*3256 * The interface doesn't need get function, so it will return the3257 * value of zero3258 * Usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_dmcub_trace_event_en3259 */3260static int dmcub_trace_event_state_get(void *data, u64 *val)3261{3262 struct amdgpu_device *adev = data;3263 3264 *val = adev->dm.dmcub_trace_event_en;3265 return 0;3266}3267 3268DEFINE_DEBUGFS_ATTRIBUTE(dmcub_trace_event_state_fops, dmcub_trace_event_state_get,3269 dmcub_trace_event_state_set, "%llu\n");3270 3271DEFINE_DEBUGFS_ATTRIBUTE(replay_state_fops, replay_get_state, NULL, "%llu\n");3272 3273DEFINE_DEBUGFS_ATTRIBUTE(psr_fops, psr_get, NULL, "%llu\n");3274DEFINE_DEBUGFS_ATTRIBUTE(psr_residency_fops, psr_read_residency, NULL,3275 "%llu\n");3276 3277DEFINE_DEBUGFS_ATTRIBUTE(allow_edp_hotplug_detection_fops,3278 allow_edp_hotplug_detection_get,3279 allow_edp_hotplug_detection_set, "%llu\n");3280 3281DEFINE_DEBUGFS_ATTRIBUTE(disallow_edp_enter_psr_fops,3282 disallow_edp_enter_psr_get,3283 disallow_edp_enter_psr_set, "%llu\n");3284 3285DEFINE_SHOW_ATTRIBUTE(current_backlight);3286DEFINE_SHOW_ATTRIBUTE(target_backlight);3287DEFINE_SHOW_ATTRIBUTE(ips_status);3288 3289static const struct {3290 char *name;3291 const struct file_operations *fops;3292} connector_debugfs_entries[] = {3293 {"force_yuv420_output", &force_yuv420_output_fops},3294 {"trigger_hotplug", &trigger_hotplug_debugfs_fops},3295 {"internal_display", &internal_display_fops},3296 {"odm_combine_segments", &odm_combine_segments_fops}3297};3298 3299/*3300 * Returns supported customized link rates by this eDP panel.3301 * Example usage: cat /sys/kernel/debug/dri/0/eDP-x/ilr_setting3302 */3303static int edp_ilr_show(struct seq_file *m, void *unused)3304{3305 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(m->private);3306 struct dc_link *link = aconnector->dc_link;3307 uint8_t supported_link_rates[16];3308 uint32_t link_rate_in_khz;3309 uint32_t entry = 0;3310 uint8_t dpcd_rev;3311 3312 memset(supported_link_rates, 0, sizeof(supported_link_rates));3313 dm_helpers_dp_read_dpcd(link->ctx, link, DP_SUPPORTED_LINK_RATES,3314 supported_link_rates, sizeof(supported_link_rates));3315 3316 dpcd_rev = link->dpcd_caps.dpcd_rev.raw;3317 3318 if (dpcd_rev >= DP_DPCD_REV_13 &&3319 (supported_link_rates[entry+1] != 0 || supported_link_rates[entry] != 0)) {3320 3321 for (entry = 0; entry < 16; entry += 2) {3322 link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 +3323 supported_link_rates[entry]) * 200;3324 seq_printf(m, "[%d] %d kHz\n", entry/2, link_rate_in_khz);3325 }3326 } else {3327 seq_puts(m, "ILR is not supported by this eDP panel.\n");3328 }3329 3330 return 0;3331}3332 3333/*3334 * Set supported customized link rate to eDP panel.3335 *3336 * echo <lane_count> <link_rate option> > ilr_setting3337 *3338 * for example, supported ILR : [0] 1620000 kHz [1] 2160000 kHz [2] 2430000 kHz ...3339 * echo 4 1 > /sys/kernel/debug/dri/0/eDP-x/ilr_setting3340 * to set 4 lanes and 2.16 GHz3341 */3342static ssize_t edp_ilr_write(struct file *f, const char __user *buf,3343 size_t size, loff_t *pos)3344{3345 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;3346 struct dc_link *link = connector->dc_link;3347 struct amdgpu_device *adev = drm_to_adev(connector->base.dev);3348 struct dc *dc = (struct dc *)link->dc;3349 struct dc_link_settings prefer_link_settings;3350 char *wr_buf = NULL;3351 const uint32_t wr_buf_size = 40;3352 /* 0: lane_count; 1: link_rate */3353 int max_param_num = 2;3354 uint8_t param_nums = 0;3355 long param[2];3356 bool valid_input = true;3357 3358 if (size == 0)3359 return -EINVAL;3360 3361 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);3362 if (!wr_buf)3363 return -ENOMEM;3364 3365 if (parse_write_buffer_into_params(wr_buf, wr_buf_size,3366 (long *)param, buf,3367 max_param_num,3368 ¶m_nums)) {3369 kfree(wr_buf);3370 return -EINVAL;3371 }3372 3373 if (param_nums <= 0) {3374 kfree(wr_buf);3375 return -EINVAL;3376 }3377 3378 switch (param[0]) {3379 case LANE_COUNT_ONE:3380 case LANE_COUNT_TWO:3381 case LANE_COUNT_FOUR:3382 break;3383 default:3384 valid_input = false;3385 break;3386 }3387 3388 if (param[1] >= link->dpcd_caps.edp_supported_link_rates_count)3389 valid_input = false;3390 3391 if (!valid_input) {3392 kfree(wr_buf);3393 DRM_DEBUG_DRIVER("Invalid Input value. No HW will be programmed\n");3394 prefer_link_settings.use_link_rate_set = false;3395 mutex_lock(&adev->dm.dc_lock);3396 dc_link_set_preferred_training_settings(dc, NULL, NULL, link, false);3397 mutex_unlock(&adev->dm.dc_lock);3398 return size;3399 }3400 3401 /* save user force lane_count, link_rate to preferred settings3402 * spread spectrum will not be changed3403 */3404 prefer_link_settings.link_spread = link->cur_link_settings.link_spread;3405 prefer_link_settings.lane_count = param[0];3406 prefer_link_settings.use_link_rate_set = true;3407 prefer_link_settings.link_rate_set = param[1];3408 prefer_link_settings.link_rate = link->dpcd_caps.edp_supported_link_rates[param[1]];3409 3410 mutex_lock(&adev->dm.dc_lock);3411 dc_link_set_preferred_training_settings(dc, &prefer_link_settings,3412 NULL, link, false);3413 mutex_unlock(&adev->dm.dc_lock);3414 3415 kfree(wr_buf);3416 return size;3417}3418 3419static int edp_ilr_open(struct inode *inode, struct file *file)3420{3421 return single_open(file, edp_ilr_show, inode->i_private);3422}3423 3424static const struct file_operations edp_ilr_debugfs_fops = {3425 .owner = THIS_MODULE,3426 .open = edp_ilr_open,3427 .read = seq_read,3428 .llseek = seq_lseek,3429 .release = single_release,3430 .write = edp_ilr_write3431};3432 3433void connector_debugfs_init(struct amdgpu_dm_connector *connector)3434{3435 int i;3436 struct dentry *dir = connector->base.debugfs_entry;3437 3438 if (connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort ||3439 connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) {3440 for (i = 0; i < ARRAY_SIZE(dp_debugfs_entries); i++) {3441 debugfs_create_file(dp_debugfs_entries[i].name,3442 0644, dir, connector,3443 dp_debugfs_entries[i].fops);3444 }3445 }3446 if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) {3447 debugfs_create_file("replay_capability", 0444, dir, connector,3448 &replay_capability_fops);3449 debugfs_create_file("replay_state", 0444, dir, connector, &replay_state_fops);3450 debugfs_create_file_unsafe("psr_capability", 0444, dir, connector, &psr_capability_fops);3451 debugfs_create_file_unsafe("psr_state", 0444, dir, connector, &psr_fops);3452 debugfs_create_file_unsafe("psr_residency", 0444, dir,3453 connector, &psr_residency_fops);3454 debugfs_create_file("amdgpu_current_backlight_pwm", 0444, dir, connector,3455 ¤t_backlight_fops);3456 debugfs_create_file("amdgpu_target_backlight_pwm", 0444, dir, connector,3457 &target_backlight_fops);3458 debugfs_create_file("ilr_setting", 0644, dir, connector,3459 &edp_ilr_debugfs_fops);3460 debugfs_create_file("allow_edp_hotplug_detection", 0644, dir, connector,3461 &allow_edp_hotplug_detection_fops);3462 debugfs_create_file("disallow_edp_enter_psr", 0644, dir, connector,3463 &disallow_edp_enter_psr_fops);3464 }3465 3466 for (i = 0; i < ARRAY_SIZE(connector_debugfs_entries); i++) {3467 debugfs_create_file(connector_debugfs_entries[i].name,3468 0644, dir, connector,3469 connector_debugfs_entries[i].fops);3470 }3471 3472 if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA) {3473 for (i = 0; i < ARRAY_SIZE(hdmi_debugfs_entries); i++) {3474 debugfs_create_file(hdmi_debugfs_entries[i].name,3475 0644, dir, connector,3476 hdmi_debugfs_entries[i].fops);3477 }3478 }3479}3480 3481#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY3482/*3483 * Set crc window coordinate x start3484 */3485static int crc_win_x_start_set(void *data, u64 val)3486{3487 struct drm_crtc *crtc = data;3488 struct drm_device *drm_dev = crtc->dev;3489 struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);3490 3491 spin_lock_irq(&drm_dev->event_lock);3492 acrtc->dm_irq_params.window_param.x_start = (uint16_t) val;3493 acrtc->dm_irq_params.window_param.update_win = false;3494 spin_unlock_irq(&drm_dev->event_lock);3495 3496 return 0;3497}3498 3499/*3500 * Get crc window coordinate x start3501 */3502static int crc_win_x_start_get(void *data, u64 *val)3503{3504 struct drm_crtc *crtc = data;3505 struct drm_device *drm_dev = crtc->dev;3506 struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);3507 3508 spin_lock_irq(&drm_dev->event_lock);3509 *val = acrtc->dm_irq_params.window_param.x_start;3510 spin_unlock_irq(&drm_dev->event_lock);3511 3512 return 0;3513}3514 3515DEFINE_DEBUGFS_ATTRIBUTE(crc_win_x_start_fops, crc_win_x_start_get,3516 crc_win_x_start_set, "%llu\n");3517 3518 3519/*3520 * Set crc window coordinate y start3521 */3522static int crc_win_y_start_set(void *data, u64 val)3523{3524 struct drm_crtc *crtc = data;3525 struct drm_device *drm_dev = crtc->dev;3526 struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);3527 3528 spin_lock_irq(&drm_dev->event_lock);3529 acrtc->dm_irq_params.window_param.y_start = (uint16_t) val;3530 acrtc->dm_irq_params.window_param.update_win = false;3531 spin_unlock_irq(&drm_dev->event_lock);3532 3533 return 0;3534}3535 3536/*3537 * Get crc window coordinate y start3538 */3539static int crc_win_y_start_get(void *data, u64 *val)3540{3541 struct drm_crtc *crtc = data;3542 struct drm_device *drm_dev = crtc->dev;3543 struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);3544 3545 spin_lock_irq(&drm_dev->event_lock);3546 *val = acrtc->dm_irq_params.window_param.y_start;3547 spin_unlock_irq(&drm_dev->event_lock);3548 3549 return 0;3550}3551 3552DEFINE_DEBUGFS_ATTRIBUTE(crc_win_y_start_fops, crc_win_y_start_get,3553 crc_win_y_start_set, "%llu\n");3554 3555/*3556 * Set crc window coordinate x end3557 */3558static int crc_win_x_end_set(void *data, u64 val)3559{3560 struct drm_crtc *crtc = data;3561 struct drm_device *drm_dev = crtc->dev;3562 struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);3563 3564 spin_lock_irq(&drm_dev->event_lock);3565 acrtc->dm_irq_params.window_param.x_end = (uint16_t) val;3566 acrtc->dm_irq_params.window_param.update_win = false;3567 spin_unlock_irq(&drm_dev->event_lock);3568 3569 return 0;3570}3571 3572/*3573 * Get crc window coordinate x end3574 */3575static int crc_win_x_end_get(void *data, u64 *val)3576{3577 struct drm_crtc *crtc = data;3578 struct drm_device *drm_dev = crtc->dev;3579 struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);3580 3581 spin_lock_irq(&drm_dev->event_lock);3582 *val = acrtc->dm_irq_params.window_param.x_end;3583 spin_unlock_irq(&drm_dev->event_lock);3584 3585 return 0;3586}3587 3588DEFINE_DEBUGFS_ATTRIBUTE(crc_win_x_end_fops, crc_win_x_end_get,3589 crc_win_x_end_set, "%llu\n");3590 3591/*3592 * Set crc window coordinate y end3593 */3594static int crc_win_y_end_set(void *data, u64 val)3595{3596 struct drm_crtc *crtc = data;3597 struct drm_device *drm_dev = crtc->dev;3598 struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);3599 3600 spin_lock_irq(&drm_dev->event_lock);3601 acrtc->dm_irq_params.window_param.y_end = (uint16_t) val;3602 acrtc->dm_irq_params.window_param.update_win = false;3603 spin_unlock_irq(&drm_dev->event_lock);3604 3605 return 0;3606}3607 3608/*3609 * Get crc window coordinate y end3610 */3611static int crc_win_y_end_get(void *data, u64 *val)3612{3613 struct drm_crtc *crtc = data;3614 struct drm_device *drm_dev = crtc->dev;3615 struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);3616 3617 spin_lock_irq(&drm_dev->event_lock);3618 *val = acrtc->dm_irq_params.window_param.y_end;3619 spin_unlock_irq(&drm_dev->event_lock);3620 3621 return 0;3622}3623 3624DEFINE_DEBUGFS_ATTRIBUTE(crc_win_y_end_fops, crc_win_y_end_get,3625 crc_win_y_end_set, "%llu\n");3626/*3627 * Trigger to commit crc window3628 */3629static int crc_win_update_set(void *data, u64 val)3630{3631 struct drm_crtc *crtc = data;3632 struct amdgpu_crtc *acrtc;3633 struct amdgpu_device *adev = drm_to_adev(crtc->dev);3634 3635 if (val) {3636 acrtc = to_amdgpu_crtc(crtc);3637 mutex_lock(&adev->dm.dc_lock);3638 /* PSR may write to OTG CRC window control register,3639 * so close it before starting secure_display.3640 */3641 amdgpu_dm_psr_disable(acrtc->dm_irq_params.stream);3642 3643 spin_lock_irq(&adev_to_drm(adev)->event_lock);3644 3645 acrtc->dm_irq_params.window_param.activated = true;3646 acrtc->dm_irq_params.window_param.update_win = true;3647 acrtc->dm_irq_params.window_param.skip_frame_cnt = 0;3648 3649 spin_unlock_irq(&adev_to_drm(adev)->event_lock);3650 mutex_unlock(&adev->dm.dc_lock);3651 }3652 3653 return 0;3654}3655 3656/*3657 * Get crc window update flag3658 */3659static int crc_win_update_get(void *data, u64 *val)3660{3661 *val = 0;3662 return 0;3663}3664 3665DEFINE_DEBUGFS_ATTRIBUTE(crc_win_update_fops, crc_win_update_get,3666 crc_win_update_set, "%llu\n");3667#endif3668void crtc_debugfs_init(struct drm_crtc *crtc)3669{3670#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY3671 struct dentry *dir = debugfs_lookup("crc", crtc->debugfs_entry);3672 3673 if (!dir)3674 return;3675 3676 debugfs_create_file_unsafe("crc_win_x_start", 0644, dir, crtc,3677 &crc_win_x_start_fops);3678 debugfs_create_file_unsafe("crc_win_y_start", 0644, dir, crtc,3679 &crc_win_y_start_fops);3680 debugfs_create_file_unsafe("crc_win_x_end", 0644, dir, crtc,3681 &crc_win_x_end_fops);3682 debugfs_create_file_unsafe("crc_win_y_end", 0644, dir, crtc,3683 &crc_win_y_end_fops);3684 debugfs_create_file_unsafe("crc_win_update", 0644, dir, crtc,3685 &crc_win_update_fops);3686 dput(dir);3687#endif3688 debugfs_create_file("amdgpu_current_bpc", 0644, crtc->debugfs_entry,3689 crtc, &amdgpu_current_bpc_fops);3690 debugfs_create_file("amdgpu_current_colorspace", 0644, crtc->debugfs_entry,3691 crtc, &amdgpu_current_colorspace_fops);3692}3693 3694/*3695 * Writes DTN log state to the user supplied buffer.3696 * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_dtn_log3697 */3698static ssize_t dtn_log_read(3699 struct file *f,3700 char __user *buf,3701 size_t size,3702 loff_t *pos)3703{3704 struct amdgpu_device *adev = file_inode(f)->i_private;3705 struct dc *dc = adev->dm.dc;3706 struct dc_log_buffer_ctx log_ctx = { 0 };3707 ssize_t result = 0;3708 3709 if (!buf || !size)3710 return -EINVAL;3711 3712 if (!dc->hwss.log_hw_state)3713 return 0;3714 3715 dc->hwss.log_hw_state(dc, &log_ctx);3716 3717 if (*pos < log_ctx.pos) {3718 size_t to_copy = log_ctx.pos - *pos;3719 3720 to_copy = min(to_copy, size);3721 3722 if (!copy_to_user(buf, log_ctx.buf + *pos, to_copy)) {3723 *pos += to_copy;3724 result = to_copy;3725 }3726 }3727 3728 kfree(log_ctx.buf);3729 3730 return result;3731}3732 3733/*3734 * Writes DTN log state to dmesg when triggered via a write.3735 * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dtn_log3736 */3737static ssize_t dtn_log_write(3738 struct file *f,3739 const char __user *buf,3740 size_t size,3741 loff_t *pos)3742{3743 struct amdgpu_device *adev = file_inode(f)->i_private;3744 struct dc *dc = adev->dm.dc;3745 3746 /* Write triggers log output via dmesg. */3747 if (size == 0)3748 return 0;3749 3750 if (dc->hwss.log_hw_state)3751 dc->hwss.log_hw_state(dc, NULL);3752 3753 return size;3754}3755 3756static int mst_topo_show(struct seq_file *m, void *unused)3757{3758 struct amdgpu_device *adev = (struct amdgpu_device *)m->private;3759 struct drm_device *dev = adev_to_drm(adev);3760 struct drm_connector *connector;3761 struct drm_connector_list_iter conn_iter;3762 struct amdgpu_dm_connector *aconnector;3763 3764 drm_connector_list_iter_begin(dev, &conn_iter);3765 drm_for_each_connector_iter(connector, &conn_iter) {3766 if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)3767 continue;3768 3769 aconnector = to_amdgpu_dm_connector(connector);3770 3771 /* Ensure we're only dumping the topology of a root mst node */3772 if (!aconnector->mst_mgr.mst_state)3773 continue;3774 3775 seq_printf(m, "\nMST topology for connector %d\n", aconnector->connector_id);3776 drm_dp_mst_dump_topology(m, &aconnector->mst_mgr);3777 }3778 drm_connector_list_iter_end(&conn_iter);3779 3780 return 0;3781}3782 3783/*3784 * Sets trigger hpd for MST topologies.3785 * All connected connectors will be rediscovered and re started as needed if val of 1 is sent.3786 * All topologies will be disconnected if val of 0 is set .3787 * Usage to enable topologies: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_trigger_hpd_mst3788 * Usage to disable topologies: echo 0 > /sys/kernel/debug/dri/0/amdgpu_dm_trigger_hpd_mst3789 */3790static int trigger_hpd_mst_set(void *data, u64 val)3791{3792 struct amdgpu_device *adev = data;3793 struct drm_device *dev = adev_to_drm(adev);3794 struct drm_connector_list_iter iter;3795 struct amdgpu_dm_connector *aconnector;3796 struct drm_connector *connector;3797 struct dc_link *link = NULL;3798 int ret;3799 3800 if (val == 1) {3801 drm_connector_list_iter_begin(dev, &iter);3802 drm_for_each_connector_iter(connector, &iter) {3803 aconnector = to_amdgpu_dm_connector(connector);3804 if (aconnector->dc_link->type == dc_connection_mst_branch &&3805 aconnector->mst_mgr.aux) {3806 mutex_lock(&adev->dm.dc_lock);3807 ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);3808 mutex_unlock(&adev->dm.dc_lock);3809 3810 if (!ret)3811 DRM_ERROR("DM_MST: Failed to detect dc link!");3812 3813 ret = drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true);3814 if (ret < 0)3815 DRM_ERROR("DM_MST: Failed to set the device into MST mode!");3816 }3817 }3818 } else if (val == 0) {3819 drm_connector_list_iter_begin(dev, &iter);3820 drm_for_each_connector_iter(connector, &iter) {3821 aconnector = to_amdgpu_dm_connector(connector);3822 if (!aconnector->dc_link)3823 continue;3824 3825 if (!aconnector->mst_root)3826 continue;3827 3828 link = aconnector->dc_link;3829 dc_link_dp_receiver_power_ctrl(link, false);3830 drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_root->mst_mgr, false);3831 link->mst_stream_alloc_table.stream_count = 0;3832 memset(link->mst_stream_alloc_table.stream_allocations, 0,3833 sizeof(link->mst_stream_alloc_table.stream_allocations));3834 }3835 } else {3836 return 0;3837 }3838 drm_kms_helper_hotplug_event(dev);3839 3840 return 0;3841}3842 3843/*3844 * The interface doesn't need get function, so it will return the3845 * value of zero3846 * Usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_trigger_hpd_mst3847 */3848static int trigger_hpd_mst_get(void *data, u64 *val)3849{3850 *val = 0;3851 return 0;3852}3853 3854DEFINE_DEBUGFS_ATTRIBUTE(trigger_hpd_mst_ops, trigger_hpd_mst_get,3855 trigger_hpd_mst_set, "%llu\n");3856 3857 3858/*3859 * Sets the force_timing_sync debug option from the given string.3860 * All connected displays will be force synchronized immediately.3861 * Usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_force_timing_sync3862 */3863static int force_timing_sync_set(void *data, u64 val)3864{3865 struct amdgpu_device *adev = data;3866 3867 adev->dm.force_timing_sync = (bool)val;3868 3869 amdgpu_dm_trigger_timing_sync(adev_to_drm(adev));3870 3871 return 0;3872}3873 3874/*3875 * Gets the force_timing_sync debug option value into the given buffer.3876 * Usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_force_timing_sync3877 */3878static int force_timing_sync_get(void *data, u64 *val)3879{3880 struct amdgpu_device *adev = data;3881 3882 *val = adev->dm.force_timing_sync;3883 3884 return 0;3885}3886 3887DEFINE_DEBUGFS_ATTRIBUTE(force_timing_sync_ops, force_timing_sync_get,3888 force_timing_sync_set, "%llu\n");3889 3890 3891/*3892 * Disables all HPD and HPD RX interrupt handling in the3893 * driver when set to 1. Default is 0.3894 */3895static int disable_hpd_set(void *data, u64 val)3896{3897 struct amdgpu_device *adev = data;3898 3899 adev->dm.disable_hpd_irq = (bool)val;3900 3901 return 0;3902}3903 3904 3905/*3906 * Returns 1 if HPD and HPRX interrupt handling is disabled,3907 * 0 otherwise.3908 */3909static int disable_hpd_get(void *data, u64 *val)3910{3911 struct amdgpu_device *adev = data;3912 3913 *val = adev->dm.disable_hpd_irq;3914 3915 return 0;3916}3917 3918DEFINE_DEBUGFS_ATTRIBUTE(disable_hpd_ops, disable_hpd_get,3919 disable_hpd_set, "%llu\n");3920 3921/*3922 * Prints hardware capabilities. These are used for IGT testing.3923 */3924static int capabilities_show(struct seq_file *m, void *unused)3925{3926 struct amdgpu_device *adev = (struct amdgpu_device *)m->private;3927 struct dc *dc = adev->dm.dc;3928 bool mall_supported = dc->caps.mall_size_total;3929 bool subvp_supported = dc->caps.subvp_fw_processing_delay_us;3930 unsigned int mall_in_use = false;3931 unsigned int subvp_in_use = false;3932 3933 struct hubbub *hubbub = dc->res_pool->hubbub;3934 3935 if (hubbub->funcs->get_mall_en)3936 hubbub->funcs->get_mall_en(hubbub, &mall_in_use);3937 3938 if (dc->cap_funcs.get_subvp_en)3939 subvp_in_use = dc->cap_funcs.get_subvp_en(dc, dc->current_state);3940 3941 seq_printf(m, "mall supported: %s, enabled: %s\n",3942 mall_supported ? "yes" : "no", mall_in_use ? "yes" : "no");3943 seq_printf(m, "sub-viewport supported: %s, enabled: %s\n",3944 subvp_supported ? "yes" : "no", subvp_in_use ? "yes" : "no");3945 3946 return 0;3947}3948 3949DEFINE_SHOW_ATTRIBUTE(capabilities);3950 3951/*3952 * Temporary w/a to force sst sequence in M42D DP2 mst receiver3953 * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dp_set_mst_en_for_sst3954 */3955static int dp_force_sst_set(void *data, u64 val)3956{3957 struct amdgpu_device *adev = data;3958 3959 adev->dm.dc->debug.set_mst_en_for_sst = val;3960 3961 return 0;3962}3963 3964static int dp_force_sst_get(void *data, u64 *val)3965{3966 struct amdgpu_device *adev = data;3967 3968 *val = adev->dm.dc->debug.set_mst_en_for_sst;3969 3970 return 0;3971}3972DEFINE_DEBUGFS_ATTRIBUTE(dp_set_mst_en_for_sst_ops, dp_force_sst_get,3973 dp_force_sst_set, "%llu\n");3974 3975/*3976 * Force DP2 sequence without VESA certified cable.3977 * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dp_ignore_cable_id3978 */3979static int dp_ignore_cable_id_set(void *data, u64 val)3980{3981 struct amdgpu_device *adev = data;3982 3983 adev->dm.dc->debug.ignore_cable_id = val;3984 3985 return 0;3986}3987 3988static int dp_ignore_cable_id_get(void *data, u64 *val)3989{3990 struct amdgpu_device *adev = data;3991 3992 *val = adev->dm.dc->debug.ignore_cable_id;3993 3994 return 0;3995}3996DEFINE_DEBUGFS_ATTRIBUTE(dp_ignore_cable_id_ops, dp_ignore_cable_id_get,3997 dp_ignore_cable_id_set, "%llu\n");3998 3999/*4000 * Sets the DC visual confirm debug option from the given string.4001 * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_visual_confirm4002 */4003static int visual_confirm_set(void *data, u64 val)4004{4005 struct amdgpu_device *adev = data;4006 4007 adev->dm.dc->debug.visual_confirm = (enum visual_confirm)val;4008 4009 return 0;4010}4011 4012/*4013 * Reads the DC visual confirm debug option value into the given buffer.4014 * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_visual_confirm4015 */4016static int visual_confirm_get(void *data, u64 *val)4017{4018 struct amdgpu_device *adev = data;4019 4020 *val = adev->dm.dc->debug.visual_confirm;4021 4022 return 0;4023}4024 4025DEFINE_SHOW_ATTRIBUTE(mst_topo);4026DEFINE_DEBUGFS_ATTRIBUTE(visual_confirm_fops, visual_confirm_get,4027 visual_confirm_set, "%llu\n");4028 4029 4030/*4031 * Sets the DC skip_detection_link_training debug option from the given string.4032 * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_skip_detection_link_training4033 */4034static int skip_detection_link_training_set(void *data, u64 val)4035{4036 struct amdgpu_device *adev = data;4037 4038 if (val == 0)4039 adev->dm.dc->debug.skip_detection_link_training = false;4040 else4041 adev->dm.dc->debug.skip_detection_link_training = true;4042 4043 return 0;4044}4045 4046/*4047 * Reads the DC skip_detection_link_training debug option value into the given buffer.4048 * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_skip_detection_link_training4049 */4050static int skip_detection_link_training_get(void *data, u64 *val)4051{4052 struct amdgpu_device *adev = data;4053 4054 *val = adev->dm.dc->debug.skip_detection_link_training;4055 4056 return 0;4057}4058 4059DEFINE_DEBUGFS_ATTRIBUTE(skip_detection_link_training_fops,4060 skip_detection_link_training_get,4061 skip_detection_link_training_set, "%llu\n");4062 4063/*4064 * Dumps the DCC_EN bit for each pipe.4065 * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_dcc_en4066 */4067static ssize_t dcc_en_bits_read(4068 struct file *f,4069 char __user *buf,4070 size_t size,4071 loff_t *pos)4072{4073 struct amdgpu_device *adev = file_inode(f)->i_private;4074 struct dc *dc = adev->dm.dc;4075 char *rd_buf = NULL;4076 const uint32_t rd_buf_size = 32;4077 uint32_t result = 0;4078 int offset = 0;4079 int num_pipes = dc->res_pool->pipe_count;4080 int *dcc_en_bits;4081 int i, r;4082 4083 dcc_en_bits = kcalloc(num_pipes, sizeof(int), GFP_KERNEL);4084 if (!dcc_en_bits)4085 return -ENOMEM;4086 4087 if (!dc->hwss.get_dcc_en_bits) {4088 kfree(dcc_en_bits);4089 return 0;4090 }4091 4092 dc->hwss.get_dcc_en_bits(dc, dcc_en_bits);4093 4094 rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);4095 if (!rd_buf) {4096 kfree(dcc_en_bits);4097 return -ENOMEM;4098 }4099 4100 for (i = 0; i < num_pipes; i++)4101 offset += snprintf(rd_buf + offset, rd_buf_size - offset,4102 "%d ", dcc_en_bits[i]);4103 rd_buf[strlen(rd_buf)] = '\n';4104 4105 kfree(dcc_en_bits);4106 4107 while (size) {4108 if (*pos >= rd_buf_size)4109 break;4110 r = put_user(*(rd_buf + result), buf);4111 if (r) {4112 kfree(rd_buf);4113 return r; /* r = -EFAULT */4114 }4115 buf += 1;4116 size -= 1;4117 *pos += 1;4118 result += 1;4119 }4120 4121 kfree(rd_buf);4122 return result;4123}4124 4125void dtn_debugfs_init(struct amdgpu_device *adev)4126{4127 static const struct file_operations dtn_log_fops = {4128 .owner = THIS_MODULE,4129 .read = dtn_log_read,4130 .write = dtn_log_write,4131 .llseek = default_llseek4132 };4133 static const struct file_operations dcc_en_bits_fops = {4134 .owner = THIS_MODULE,4135 .read = dcc_en_bits_read,4136 .llseek = default_llseek4137 };4138 4139 struct drm_minor *minor = adev_to_drm(adev)->primary;4140 struct dentry *root = minor->debugfs_root;4141 4142 debugfs_create_file("amdgpu_mst_topology", 0444, root,4143 adev, &mst_topo_fops);4144 debugfs_create_file("amdgpu_dm_capabilities", 0444, root,4145 adev, &capabilities_fops);4146 debugfs_create_file("amdgpu_dm_dtn_log", 0644, root, adev,4147 &dtn_log_fops);4148 debugfs_create_file("amdgpu_dm_dp_set_mst_en_for_sst", 0644, root, adev,4149 &dp_set_mst_en_for_sst_ops);4150 debugfs_create_file("amdgpu_dm_dp_ignore_cable_id", 0644, root, adev,4151 &dp_ignore_cable_id_ops);4152 4153 debugfs_create_file_unsafe("amdgpu_dm_visual_confirm", 0644, root, adev,4154 &visual_confirm_fops);4155 4156 debugfs_create_file_unsafe("amdgpu_dm_skip_detection_link_training", 0644, root, adev,4157 &skip_detection_link_training_fops);4158 4159 debugfs_create_file_unsafe("amdgpu_dm_dmub_tracebuffer", 0644, root,4160 adev, &dmub_tracebuffer_fops);4161 4162 debugfs_create_file_unsafe("amdgpu_dm_dmub_fw_state", 0644, root,4163 adev, &dmub_fw_state_fops);4164 4165 debugfs_create_file_unsafe("amdgpu_dm_force_timing_sync", 0644, root,4166 adev, &force_timing_sync_ops);4167 4168 debugfs_create_file_unsafe("amdgpu_dm_dmub_trace_mask", 0644, root,4169 adev, &dmub_trace_mask_fops);4170 4171 debugfs_create_file_unsafe("amdgpu_dm_dmcub_trace_event_en", 0644, root,4172 adev, &dmcub_trace_event_state_fops);4173 4174 debugfs_create_file_unsafe("amdgpu_dm_trigger_hpd_mst", 0644, root,4175 adev, &trigger_hpd_mst_ops);4176 4177 debugfs_create_file_unsafe("amdgpu_dm_dcc_en", 0644, root, adev,4178 &dcc_en_bits_fops);4179 4180 debugfs_create_file_unsafe("amdgpu_dm_disable_hpd", 0644, root, adev,4181 &disable_hpd_ops);4182 4183 if (adev->dm.dc->caps.ips_support)4184 debugfs_create_file_unsafe("amdgpu_dm_ips_status", 0644, root, adev,4185 &ips_status_fops);4186}4187