Home | History | Annotate | Line # | Download | only in amdgpu_dm
      1 /*	$NetBSD: amdgpu_dm_debugfs.c,v 1.2 2021/12/18 23:45:00 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2018 Advanced Micro Devices, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors: AMD
     25  *
     26  */
     27 
     28 #include <sys/cdefs.h>
     29 __KERNEL_RCSID(0, "$NetBSD: amdgpu_dm_debugfs.c,v 1.2 2021/12/18 23:45:00 riastradh Exp $");
     30 
     31 #include <linux/uaccess.h>
     32 
     33 #include <drm/drm_debugfs.h>
     34 
     35 #include "dc.h"
     36 #include "amdgpu.h"
     37 #include "amdgpu_dm.h"
     38 #include "amdgpu_dm_debugfs.h"
     39 #include "dm_helpers.h"
     40 
     41 /* function description
     42  * get/ set DP configuration: lane_count, link_rate, spread_spectrum
     43  *
     44  * valid lane count value: 1, 2, 4
     45  * valid link rate value:
     46  * 06h = 1.62Gbps per lane
     47  * 0Ah = 2.7Gbps per lane
     48  * 0Ch = 3.24Gbps per lane
     49  * 14h = 5.4Gbps per lane
     50  * 1Eh = 8.1Gbps per lane
     51  *
     52  * debugfs is located at /sys/kernel/debug/dri/0/DP-x/link_settings
     53  *
     54  * --- to get dp configuration
     55  *
     56  * cat link_settings
     57  *
     58  * It will list current, verified, reported, preferred dp configuration.
     59  * current -- for current video mode
     60  * verified --- maximum configuration which pass link training
     61  * reported --- DP rx report caps (DPCD register offset 0, 1 2)
     62  * preferred --- user force settings
     63  *
     64  * --- set (or force) dp configuration
     65  *
     66  * echo <lane_count>  <link_rate> > link_settings
     67  *
     68  * for example, to force to  2 lane, 2.7GHz,
     69  * echo 4 0xa > link_settings
     70  *
     71  * spread_spectrum could not be changed dynamically.
     72  *
     73  * in case invalid lane count, link rate are force, no hw programming will be
     74  * done. please check link settings after force operation to see if HW get
     75  * programming.
     76  *
     77  * cat link_settings
     78  *
     79  * check current and preferred settings.
     80  *
     81  */
     82 static ssize_t dp_link_settings_read(struct file *f, char __user *buf,
     83 				 size_t size, loff_t *pos)
     84 {
     85 	struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
     86 	struct dc_link *link = connector->dc_link;
     87 	char *rd_buf = NULL;
     88 	char *rd_buf_ptr = NULL;
     89 	const uint32_t rd_buf_size = 100;
     90 	uint32_t result = 0;
     91 	uint8_t str_len = 0;
     92 	int r;
     93 
     94 	if (*pos & 3 || size & 3)
     95 		return -EINVAL;
     96 
     97 	rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
     98 	if (!rd_buf)
     99 		return 0;
    100 
    101 	rd_buf_ptr = rd_buf;
    102 
    103 	str_len = strlen("Current:  %d  %d  %d  ");
    104 	snprintf(rd_buf_ptr, str_len, "Current:  %d  %d  %d  ",
    105 			link->cur_link_settings.lane_count,
    106 			link->cur_link_settings.link_rate,
    107 			link->cur_link_settings.link_spread);
    108 	rd_buf_ptr += str_len;
    109 
    110 	str_len = strlen("Verified:  %d  %d  %d  ");
    111 	snprintf(rd_buf_ptr, str_len, "Verified:  %d  %d  %d  ",
    112 			link->verified_link_cap.lane_count,
    113 			link->verified_link_cap.link_rate,
    114 			link->verified_link_cap.link_spread);
    115 	rd_buf_ptr += str_len;
    116 
    117 	str_len = strlen("Reported:  %d  %d  %d  ");
    118 	snprintf(rd_buf_ptr, str_len, "Reported:  %d  %d  %d  ",
    119 			link->reported_link_cap.lane_count,
    120 			link->reported_link_cap.link_rate,
    121 			link->reported_link_cap.link_spread);
    122 	rd_buf_ptr += str_len;
    123 
    124 	str_len = strlen("Preferred:  %d  %d  %d  ");
    125 	snprintf(rd_buf_ptr, str_len, "Preferred:  %d  %d  %d\n",
    126 			link->preferred_link_setting.lane_count,
    127 			link->preferred_link_setting.link_rate,
    128 			link->preferred_link_setting.link_spread);
    129 
    130 	while (size) {
    131 		if (*pos >= rd_buf_size)
    132 			break;
    133 
    134 		r = put_user(*(rd_buf + result), buf);
    135 		if (r)
    136 			return r; /* r = -EFAULT */
    137 
    138 		buf += 1;
    139 		size -= 1;
    140 		*pos += 1;
    141 		result += 1;
    142 	}
    143 
    144 	kfree(rd_buf);
    145 	return result;
    146 }
    147 
    148 static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
    149 				 size_t size, loff_t *pos)
    150 {
    151 	struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
    152 	struct dc_link *link = connector->dc_link;
    153 	struct dc *dc = (struct dc *)link->dc;
    154 	struct dc_link_settings prefer_link_settings;
    155 	char *wr_buf = NULL;
    156 	char *wr_buf_ptr = NULL;
    157 	const uint32_t wr_buf_size = 40;
    158 	int r;
    159 	int bytes_from_user;
    160 	char *sub_str;
    161 	/* 0: lane_count; 1: link_rate */
    162 	uint8_t param_index = 0;
    163 	long param[2];
    164 	const char delimiter[3] = {' ', '\n', '\0'};
    165 	bool valid_input = false;
    166 
    167 	if (size == 0)
    168 		return -EINVAL;
    169 
    170 	wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
    171 	if (!wr_buf)
    172 		return -EINVAL;
    173 	wr_buf_ptr = wr_buf;
    174 
    175 	r = copy_from_user(wr_buf_ptr, buf, wr_buf_size);
    176 
    177 	/* r is bytes not be copied */
    178 	if (r >= wr_buf_size) {
    179 		kfree(wr_buf);
    180 		DRM_DEBUG_DRIVER("user data not read\n");
    181 		return -EINVAL;
    182 	}
    183 
    184 	bytes_from_user = wr_buf_size - r;
    185 
    186 	while (isspace(*wr_buf_ptr))
    187 		wr_buf_ptr++;
    188 
    189 	while ((*wr_buf_ptr != '\0') && (param_index < 2)) {
    190 
    191 		sub_str = strsep(&wr_buf_ptr, delimiter);
    192 
    193 		r = kstrtol(sub_str, 16, &param[param_index]);
    194 
    195 		if (r)
    196 			DRM_DEBUG_DRIVER("string to int convert error code: %d\n", r);
    197 
    198 		param_index++;
    199 		while (isspace(*wr_buf_ptr))
    200 			wr_buf_ptr++;
    201 	}
    202 
    203 	switch (param[0]) {
    204 	case LANE_COUNT_ONE:
    205 	case LANE_COUNT_TWO:
    206 	case LANE_COUNT_FOUR:
    207 		valid_input = true;
    208 		break;
    209 	default:
    210 		break;
    211 	}
    212 
    213 	switch (param[1]) {
    214 	case LINK_RATE_LOW:
    215 	case LINK_RATE_HIGH:
    216 	case LINK_RATE_RBR2:
    217 	case LINK_RATE_HIGH2:
    218 	case LINK_RATE_HIGH3:
    219 		valid_input = true;
    220 		break;
    221 	default:
    222 		break;
    223 	}
    224 
    225 	if (!valid_input) {
    226 		kfree(wr_buf);
    227 		DRM_DEBUG_DRIVER("Invalid Input value No HW will be programmed\n");
    228 		return bytes_from_user;
    229 	}
    230 
    231 	/* save user force lane_count, link_rate to preferred settings
    232 	 * spread spectrum will not be changed
    233 	 */
    234 	prefer_link_settings.link_spread = link->cur_link_settings.link_spread;
    235 	prefer_link_settings.lane_count = param[0];
    236 	prefer_link_settings.link_rate = param[1];
    237 
    238 	dc_link_set_preferred_link_settings(dc, &prefer_link_settings, link);
    239 
    240 	kfree(wr_buf);
    241 	return bytes_from_user;
    242 }
    243 
    244 /* function: get current DP PHY settings: voltage swing, pre-emphasis,
    245  * post-cursor2 (defined by VESA DP specification)
    246  *
    247  * valid values
    248  * voltage swing: 0,1,2,3
    249  * pre-emphasis : 0,1,2,3
    250  * post cursor2 : 0,1,2,3
    251  *
    252  *
    253  * how to use this debugfs
    254  *
    255  * debugfs is located at /sys/kernel/debug/dri/0/DP-x
    256  *
    257  * there will be directories, like DP-1, DP-2,DP-3, etc. for DP display
    258  *
    259  * To figure out which DP-x is the display for DP to be check,
    260  * cd DP-x
    261  * ls -ll
    262  * There should be debugfs file, like link_settings, phy_settings.
    263  * cat link_settings
    264  * from lane_count, link_rate to figure which DP-x is for display to be worked
    265  * on
    266  *
    267  * To get current DP PHY settings,
    268  * cat phy_settings
    269  *
    270  * To change DP PHY settings,
    271  * echo <voltage_swing> <pre-emphasis> <post_cursor2> > phy_settings
    272  * for examle, to change voltage swing to 2, pre-emphasis to 3, post_cursor2 to
    273  * 0,
    274  * echo 2 3 0 > phy_settings
    275  *
    276  * To check if change be applied, get current phy settings by
    277  * cat phy_settings
    278  *
    279  * In case invalid values are set by user, like
    280  * echo 1 4 0 > phy_settings
    281  *
    282  * HW will NOT be programmed by these settings.
    283  * cat phy_settings will show the previous valid settings.
    284  */
    285 static ssize_t dp_phy_settings_read(struct file *f, char __user *buf,
    286 				 size_t size, loff_t *pos)
    287 {
    288 	struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
    289 	struct dc_link *link = connector->dc_link;
    290 	char *rd_buf = NULL;
    291 	const uint32_t rd_buf_size = 20;
    292 	uint32_t result = 0;
    293 	int r;
    294 
    295 	if (*pos & 3 || size & 3)
    296 		return -EINVAL;
    297 
    298 	rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
    299 	if (!rd_buf)
    300 		return -EINVAL;
    301 
    302 	snprintf(rd_buf, rd_buf_size, "  %d  %d  %d  ",
    303 			link->cur_lane_setting.VOLTAGE_SWING,
    304 			link->cur_lane_setting.PRE_EMPHASIS,
    305 			link->cur_lane_setting.POST_CURSOR2);
    306 
    307 	while (size) {
    308 		if (*pos >= rd_buf_size)
    309 			break;
    310 
    311 		r = put_user((*(rd_buf + result)), buf);
    312 		if (r)
    313 			return r; /* r = -EFAULT */
    314 
    315 		buf += 1;
    316 		size -= 1;
    317 		*pos += 1;
    318 		result += 1;
    319 	}
    320 
    321 	kfree(rd_buf);
    322 	return result;
    323 }
    324 
    325 static ssize_t dp_phy_settings_write(struct file *f, const char __user *buf,
    326 				 size_t size, loff_t *pos)
    327 {
    328 	struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
    329 	struct dc_link *link = connector->dc_link;
    330 	struct dc *dc = (struct dc *)link->dc;
    331 	char *wr_buf = NULL;
    332 	char *wr_buf_ptr = NULL;
    333 	uint32_t wr_buf_size = 40;
    334 	int r;
    335 	int bytes_from_user;
    336 	char *sub_str;
    337 	uint8_t param_index = 0;
    338 	long param[3];
    339 	const char delimiter[3] = {' ', '\n', '\0'};
    340 	bool use_prefer_link_setting;
    341 	struct link_training_settings link_lane_settings;
    342 
    343 	if (size == 0)
    344 		return 0;
    345 
    346 	wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
    347 	if (!wr_buf)
    348 		return 0;
    349 	wr_buf_ptr = wr_buf;
    350 
    351 	r = copy_from_user(wr_buf_ptr, buf, wr_buf_size);
    352 
    353 	/* r is bytes not be copied */
    354 	if (r >= wr_buf_size) {
    355 		kfree(wr_buf);
    356 		DRM_DEBUG_DRIVER("user data not be read\n");
    357 		return 0;
    358 	}
    359 
    360 	bytes_from_user = wr_buf_size - r;
    361 
    362 	while (isspace(*wr_buf_ptr))
    363 		wr_buf_ptr++;
    364 
    365 	while ((*wr_buf_ptr != '\0') && (param_index < 3)) {
    366 
    367 		sub_str = strsep(&wr_buf_ptr, delimiter);
    368 
    369 		r = kstrtol(sub_str, 16, &param[param_index]);
    370 
    371 		if (r)
    372 			DRM_DEBUG_DRIVER("string to int convert error code: %d\n", r);
    373 
    374 		param_index++;
    375 		while (isspace(*wr_buf_ptr))
    376 			wr_buf_ptr++;
    377 	}
    378 
    379 	if ((param[0] > VOLTAGE_SWING_MAX_LEVEL) ||
    380 			(param[1] > PRE_EMPHASIS_MAX_LEVEL) ||
    381 			(param[2] > POST_CURSOR2_MAX_LEVEL)) {
    382 		kfree(wr_buf);
    383 		DRM_DEBUG_DRIVER("Invalid Input No HW will be programmed\n");
    384 		return bytes_from_user;
    385 	}
    386 
    387 	/* get link settings: lane count, link rate */
    388 	use_prefer_link_setting =
    389 		((link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN) &&
    390 		(link->test_pattern_enabled));
    391 
    392 	memset(&link_lane_settings, 0, sizeof(link_lane_settings));
    393 
    394 	if (use_prefer_link_setting) {
    395 		link_lane_settings.link_settings.lane_count =
    396 				link->preferred_link_setting.lane_count;
    397 		link_lane_settings.link_settings.link_rate =
    398 				link->preferred_link_setting.link_rate;
    399 		link_lane_settings.link_settings.link_spread =
    400 				link->preferred_link_setting.link_spread;
    401 	} else {
    402 		link_lane_settings.link_settings.lane_count =
    403 				link->cur_link_settings.lane_count;
    404 		link_lane_settings.link_settings.link_rate =
    405 				link->cur_link_settings.link_rate;
    406 		link_lane_settings.link_settings.link_spread =
    407 				link->cur_link_settings.link_spread;
    408 	}
    409 
    410 	/* apply phy settings from user */
    411 	for (r = 0; r < link_lane_settings.link_settings.lane_count; r++) {
    412 		link_lane_settings.lane_settings[r].VOLTAGE_SWING =
    413 				(enum dc_voltage_swing) (param[0]);
    414 		link_lane_settings.lane_settings[r].PRE_EMPHASIS =
    415 				(enum dc_pre_emphasis) (param[1]);
    416 		link_lane_settings.lane_settings[r].POST_CURSOR2 =
    417 				(enum dc_post_cursor2) (param[2]);
    418 	}
    419 
    420 	/* program ASIC registers and DPCD registers */
    421 	dc_link_set_drive_settings(dc, &link_lane_settings, link);
    422 
    423 	kfree(wr_buf);
    424 	return bytes_from_user;
    425 }
    426 
    427 /* function description
    428  *
    429  * set PHY layer or Link layer test pattern
    430  * PHY test pattern is used for PHY SI check.
    431  * Link layer test will not affect PHY SI.
    432  *
    433  * Reset Test Pattern:
    434  * 0 = DP_TEST_PATTERN_VIDEO_MODE
    435  *
    436  * PHY test pattern supported:
    437  * 1 = DP_TEST_PATTERN_D102
    438  * 2 = DP_TEST_PATTERN_SYMBOL_ERROR
    439  * 3 = DP_TEST_PATTERN_PRBS7
    440  * 4 = DP_TEST_PATTERN_80BIT_CUSTOM
    441  * 5 = DP_TEST_PATTERN_CP2520_1
    442  * 6 = DP_TEST_PATTERN_CP2520_2 = DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE
    443  * 7 = DP_TEST_PATTERN_CP2520_3
    444  *
    445  * DP PHY Link Training Patterns
    446  * 8 = DP_TEST_PATTERN_TRAINING_PATTERN1
    447  * 9 = DP_TEST_PATTERN_TRAINING_PATTERN2
    448  * a = DP_TEST_PATTERN_TRAINING_PATTERN3
    449  * b = DP_TEST_PATTERN_TRAINING_PATTERN4
    450  *
    451  * DP Link Layer Test pattern
    452  * c = DP_TEST_PATTERN_COLOR_SQUARES
    453  * d = DP_TEST_PATTERN_COLOR_SQUARES_CEA
    454  * e = DP_TEST_PATTERN_VERTICAL_BARS
    455  * f = DP_TEST_PATTERN_HORIZONTAL_BARS
    456  * 10= DP_TEST_PATTERN_COLOR_RAMP
    457  *
    458  * debugfs phy_test_pattern is located at /syskernel/debug/dri/0/DP-x
    459  *
    460  * --- set test pattern
    461  * echo <test pattern #> > test_pattern
    462  *
    463  * If test pattern # is not supported, NO HW programming will be done.
    464  * for DP_TEST_PATTERN_80BIT_CUSTOM, it needs extra 10 bytes of data
    465  * for the user pattern. input 10 bytes data are separated by space
    466  *
    467  * echo 0x4 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x99 0xaa > test_pattern
    468  *
    469  * --- reset test pattern
    470  * echo 0 > test_pattern
    471  *
    472  * --- HPD detection is disabled when set PHY test pattern
    473  *
    474  * when PHY test pattern (pattern # within [1,7]) is set, HPD pin of HW ASIC
    475  * is disable. User could unplug DP display from DP connected and plug scope to
    476  * check test pattern PHY SI.
    477  * If there is need unplug scope and plug DP display back, do steps below:
    478  * echo 0 > phy_test_pattern
    479  * unplug scope
    480  * plug DP display.
    481  *
    482  * "echo 0 > phy_test_pattern" will re-enable HPD pin again so that video sw
    483  * driver could detect "unplug scope" and "plug DP display"
    484  */
    485 static ssize_t dp_phy_test_pattern_debugfs_write(struct file *f, const char __user *buf,
    486 				 size_t size, loff_t *pos)
    487 {
    488 	struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
    489 	struct dc_link *link = connector->dc_link;
    490 	char *wr_buf = NULL;
    491 	char *wr_buf_ptr = NULL;
    492 	uint32_t wr_buf_size = 100;
    493 	uint32_t wr_buf_count = 0;
    494 	int r;
    495 	int bytes_from_user;
    496 	char *sub_str = NULL;
    497 	uint8_t param_index = 0;
    498 	uint8_t param_nums = 0;
    499 	long param[11] = {0x0};
    500 	const char delimiter[3] = {' ', '\n', '\0'};
    501 	enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
    502 	bool disable_hpd = false;
    503 	bool valid_test_pattern = false;
    504 	/* init with defalut 80bit custom pattern */
    505 	uint8_t custom_pattern[10] = {
    506 			0x1f, 0x7c, 0xf0, 0xc1, 0x07,
    507 			0x1f, 0x7c, 0xf0, 0xc1, 0x07
    508 			};
    509 	struct dc_link_settings prefer_link_settings = {LANE_COUNT_UNKNOWN,
    510 			LINK_RATE_UNKNOWN, LINK_SPREAD_DISABLED};
    511 	struct dc_link_settings cur_link_settings = {LANE_COUNT_UNKNOWN,
    512 			LINK_RATE_UNKNOWN, LINK_SPREAD_DISABLED};
    513 	struct link_training_settings link_training_settings;
    514 	int i;
    515 
    516 	if (size == 0)
    517 		return 0;
    518 
    519 	wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
    520 	if (!wr_buf)
    521 		return 0;
    522 	wr_buf_ptr = wr_buf;
    523 
    524 	r = copy_from_user(wr_buf_ptr, buf, wr_buf_size);
    525 
    526 	/* r is bytes not be copied */
    527 	if (r >= wr_buf_size) {
    528 		kfree(wr_buf);
    529 		DRM_DEBUG_DRIVER("user data not be read\n");
    530 		return 0;
    531 	}
    532 
    533 	bytes_from_user = wr_buf_size - r;
    534 
    535 	/* check number of parameters. isspace could not differ space and \n */
    536 	while ((*wr_buf_ptr != 0xa) && (wr_buf_count < wr_buf_size)) {
    537 		/* skip space*/
    538 		while (isspace(*wr_buf_ptr) && (wr_buf_count < wr_buf_size)) {
    539 			wr_buf_ptr++;
    540 			wr_buf_count++;
    541 			}
    542 
    543 		if (wr_buf_count == wr_buf_size)
    544 			break;
    545 
    546 		/* skip non-space*/
    547 		while ((!isspace(*wr_buf_ptr)) && (wr_buf_count < wr_buf_size)) {
    548 			wr_buf_ptr++;
    549 			wr_buf_count++;
    550 			}
    551 
    552 		param_nums++;
    553 
    554 		if (wr_buf_count == wr_buf_size)
    555 			break;
    556 	}
    557 
    558 	/* max 11 parameters */
    559 	if (param_nums > 11)
    560 		param_nums = 11;
    561 
    562 	wr_buf_ptr = wr_buf; /* reset buf pinter */
    563 	wr_buf_count = 0; /* number of char already checked */
    564 
    565 	while (isspace(*wr_buf_ptr) && (wr_buf_count < wr_buf_size)) {
    566 		wr_buf_ptr++;
    567 		wr_buf_count++;
    568 	}
    569 
    570 	while (param_index < param_nums) {
    571 		/* after strsep, wr_buf_ptr will be moved to after space */
    572 		sub_str = strsep(&wr_buf_ptr, delimiter);
    573 
    574 		r = kstrtol(sub_str, 16, &param[param_index]);
    575 
    576 		if (r)
    577 			DRM_DEBUG_DRIVER("string to int convert error code: %d\n", r);
    578 
    579 		param_index++;
    580 	}
    581 
    582 	test_pattern = param[0];
    583 
    584 	switch (test_pattern) {
    585 	case DP_TEST_PATTERN_VIDEO_MODE:
    586 	case DP_TEST_PATTERN_COLOR_SQUARES:
    587 	case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
    588 	case DP_TEST_PATTERN_VERTICAL_BARS:
    589 	case DP_TEST_PATTERN_HORIZONTAL_BARS:
    590 	case DP_TEST_PATTERN_COLOR_RAMP:
    591 		valid_test_pattern = true;
    592 		break;
    593 
    594 	case DP_TEST_PATTERN_D102:
    595 	case DP_TEST_PATTERN_SYMBOL_ERROR:
    596 	case DP_TEST_PATTERN_PRBS7:
    597 	case DP_TEST_PATTERN_80BIT_CUSTOM:
    598 	case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE:
    599 	case DP_TEST_PATTERN_TRAINING_PATTERN4:
    600 		disable_hpd = true;
    601 		valid_test_pattern = true;
    602 		break;
    603 
    604 	default:
    605 		valid_test_pattern = false;
    606 		test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
    607 		break;
    608 	}
    609 
    610 	if (!valid_test_pattern) {
    611 		kfree(wr_buf);
    612 		DRM_DEBUG_DRIVER("Invalid Test Pattern Parameters\n");
    613 		return bytes_from_user;
    614 	}
    615 
    616 	if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) {
    617 		for (i = 0; i < 10; i++) {
    618 			if ((uint8_t) param[i + 1] != 0x0)
    619 				break;
    620 		}
    621 
    622 		if (i < 10) {
    623 			/* not use default value */
    624 			for (i = 0; i < 10; i++)
    625 				custom_pattern[i] = (uint8_t) param[i + 1];
    626 		}
    627 	}
    628 
    629 	/* Usage: set DP physical test pattern using debugfs with normal DP
    630 	 * panel. Then plug out DP panel and connect a scope to measure
    631 	 * For normal video mode and test pattern generated from CRCT,
    632 	 * they are visibile to user. So do not disable HPD.
    633 	 * Video Mode is also set to clear the test pattern, so enable HPD
    634 	 * because it might have been disabled after a test pattern was set.
    635 	 * AUX depends on HPD * sequence dependent, do not move!
    636 	 */
    637 	if (!disable_hpd)
    638 		dc_link_enable_hpd(link);
    639 
    640 	prefer_link_settings.lane_count = link->verified_link_cap.lane_count;
    641 	prefer_link_settings.link_rate = link->verified_link_cap.link_rate;
    642 	prefer_link_settings.link_spread = link->verified_link_cap.link_spread;
    643 
    644 	cur_link_settings.lane_count = link->cur_link_settings.lane_count;
    645 	cur_link_settings.link_rate = link->cur_link_settings.link_rate;
    646 	cur_link_settings.link_spread = link->cur_link_settings.link_spread;
    647 
    648 	link_training_settings.link_settings = cur_link_settings;
    649 
    650 
    651 	if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
    652 		if (prefer_link_settings.lane_count != LANE_COUNT_UNKNOWN &&
    653 			prefer_link_settings.link_rate !=  LINK_RATE_UNKNOWN &&
    654 			(prefer_link_settings.lane_count != cur_link_settings.lane_count ||
    655 			prefer_link_settings.link_rate != cur_link_settings.link_rate))
    656 			link_training_settings.link_settings = prefer_link_settings;
    657 	}
    658 
    659 	for (i = 0; i < (unsigned int)(link_training_settings.link_settings.lane_count); i++)
    660 		link_training_settings.lane_settings[i] = link->cur_lane_setting;
    661 
    662 	dc_link_set_test_pattern(
    663 		link,
    664 		test_pattern,
    665 		DP_TEST_PATTERN_COLOR_SPACE_RGB,
    666 		&link_training_settings,
    667 		custom_pattern,
    668 		10);
    669 
    670 	/* Usage: Set DP physical test pattern using AMDDP with normal DP panel
    671 	 * Then plug out DP panel and connect a scope to measure DP PHY signal.
    672 	 * Need disable interrupt to avoid SW driver disable DP output. This is
    673 	 * done after the test pattern is set.
    674 	 */
    675 	if (valid_test_pattern && disable_hpd)
    676 		dc_link_disable_hpd(link);
    677 
    678 	kfree(wr_buf);
    679 
    680 	return bytes_from_user;
    681 }
    682 
    683 /*
    684  * Returns the current and maximum output bpc for the connector.
    685  * Example usage: cat /sys/kernel/debug/dri/0/DP-1/output_bpc
    686  */
    687 static int output_bpc_show(struct seq_file *m, void *data)
    688 {
    689 	struct drm_connector *connector = m->private;
    690 	struct drm_device *dev = connector->dev;
    691 	struct drm_crtc *crtc = NULL;
    692 	struct dm_crtc_state *dm_crtc_state = NULL;
    693 	int res = -ENODEV;
    694 	unsigned int bpc;
    695 
    696 	mutex_lock(&dev->mode_config.mutex);
    697 	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
    698 
    699 	if (connector->state == NULL)
    700 		goto unlock;
    701 
    702 	crtc = connector->state->crtc;
    703 	if (crtc == NULL)
    704 		goto unlock;
    705 
    706 	drm_modeset_lock(&crtc->mutex, NULL);
    707 	if (crtc->state == NULL)
    708 		goto unlock;
    709 
    710 	dm_crtc_state = to_dm_crtc_state(crtc->state);
    711 	if (dm_crtc_state->stream == NULL)
    712 		goto unlock;
    713 
    714 	switch (dm_crtc_state->stream->timing.display_color_depth) {
    715 	case COLOR_DEPTH_666:
    716 		bpc = 6;
    717 		break;
    718 	case COLOR_DEPTH_888:
    719 		bpc = 8;
    720 		break;
    721 	case COLOR_DEPTH_101010:
    722 		bpc = 10;
    723 		break;
    724 	case COLOR_DEPTH_121212:
    725 		bpc = 12;
    726 		break;
    727 	case COLOR_DEPTH_161616:
    728 		bpc = 16;
    729 		break;
    730 	default:
    731 		goto unlock;
    732 	}
    733 
    734 	seq_printf(m, "Current: %u\n", bpc);
    735 	seq_printf(m, "Maximum: %u\n", connector->display_info.bpc);
    736 	res = 0;
    737 
    738 unlock:
    739 	if (crtc)
    740 		drm_modeset_unlock(&crtc->mutex);
    741 
    742 	drm_modeset_unlock(&dev->mode_config.connection_mutex);
    743 	mutex_unlock(&dev->mode_config.mutex);
    744 
    745 	return res;
    746 }
    747 
    748 /*
    749  * Returns the min and max vrr vfreq through the connector's debugfs file.
    750  * Example usage: cat /sys/kernel/debug/dri/0/DP-1/vrr_range
    751  */
    752 static int vrr_range_show(struct seq_file *m, void *data)
    753 {
    754 	struct drm_connector *connector = m->private;
    755 	struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
    756 
    757 	if (connector->status != connector_status_connected)
    758 		return -ENODEV;
    759 
    760 	seq_printf(m, "Min: %u\n", (unsigned int)aconnector->min_vfreq);
    761 	seq_printf(m, "Max: %u\n", (unsigned int)aconnector->max_vfreq);
    762 
    763 	return 0;
    764 }
    765 
    766 /* function description
    767  *
    768  * generic SDP message access for testing
    769  *
    770  * debugfs sdp_message is located at /syskernel/debug/dri/0/DP-x
    771  *
    772  * SDP header
    773  * Hb0 : Secondary-Data Packet ID
    774  * Hb1 : Secondary-Data Packet type
    775  * Hb2 : Secondary-Data-packet-specific header, Byte 0
    776  * Hb3 : Secondary-Data-packet-specific header, Byte 1
    777  *
    778  * for using custom sdp message: input 4 bytes SDP header and 32 bytes raw data
    779  */
    780 static ssize_t dp_sdp_message_debugfs_write(struct file *f, const char __user *buf,
    781 				 size_t size, loff_t *pos)
    782 {
    783 	int r;
    784 	uint8_t data[36];
    785 	struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
    786 	struct dm_crtc_state *acrtc_state;
    787 	uint32_t write_size = 36;
    788 
    789 	if (connector->base.status != connector_status_connected)
    790 		return -ENODEV;
    791 
    792 	if (size == 0)
    793 		return 0;
    794 
    795 	acrtc_state = to_dm_crtc_state(connector->base.state->crtc->state);
    796 
    797 	r = copy_from_user(data, buf, write_size);
    798 
    799 	write_size -= r;
    800 
    801 	dc_stream_send_dp_sdp(acrtc_state->stream, data, write_size);
    802 
    803 	return write_size;
    804 }
    805 
    806 static ssize_t dp_dpcd_address_write(struct file *f, const char __user *buf,
    807 				 size_t size, loff_t *pos)
    808 {
    809 	int r;
    810 	struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
    811 
    812 	if (size < sizeof(connector->debugfs_dpcd_address))
    813 		return 0;
    814 
    815 	r = copy_from_user(&connector->debugfs_dpcd_address,
    816 			buf, sizeof(connector->debugfs_dpcd_address));
    817 
    818 	return size - r;
    819 }
    820 
    821 static ssize_t dp_dpcd_size_write(struct file *f, const char __user *buf,
    822 				 size_t size, loff_t *pos)
    823 {
    824 	int r;
    825 	struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
    826 
    827 	if (size < sizeof(connector->debugfs_dpcd_size))
    828 		return 0;
    829 
    830 	r = copy_from_user(&connector->debugfs_dpcd_size,
    831 			buf, sizeof(connector->debugfs_dpcd_size));
    832 
    833 	if (connector->debugfs_dpcd_size > 256)
    834 		connector->debugfs_dpcd_size = 0;
    835 
    836 	return size - r;
    837 }
    838 
    839 static ssize_t dp_dpcd_data_write(struct file *f, const char __user *buf,
    840 				 size_t size, loff_t *pos)
    841 {
    842 	int r;
    843 	char *data;
    844 	struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
    845 	struct dc_link *link = connector->dc_link;
    846 	uint32_t write_size = connector->debugfs_dpcd_size;
    847 
    848 	if (size < write_size)
    849 		return 0;
    850 
    851 	data = kzalloc(write_size, GFP_KERNEL);
    852 	if (!data)
    853 		return 0;
    854 
    855 	r = copy_from_user(data, buf, write_size);
    856 
    857 	dm_helpers_dp_write_dpcd(link->ctx, link,
    858 			connector->debugfs_dpcd_address, data, write_size - r);
    859 	kfree(data);
    860 	return write_size - r;
    861 }
    862 
    863 static ssize_t dp_dpcd_data_read(struct file *f, char __user *buf,
    864 				 size_t size, loff_t *pos)
    865 {
    866 	int r;
    867 	char *data;
    868 	struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
    869 	struct dc_link *link = connector->dc_link;
    870 	uint32_t read_size = connector->debugfs_dpcd_size;
    871 
    872 	if (size < read_size)
    873 		return 0;
    874 
    875 	data = kzalloc(read_size, GFP_KERNEL);
    876 	if (!data)
    877 		return 0;
    878 
    879 	dm_helpers_dp_read_dpcd(link->ctx, link,
    880 			connector->debugfs_dpcd_address, data, read_size);
    881 
    882 	r = copy_to_user(buf, data, read_size);
    883 
    884 	kfree(data);
    885 	return read_size - r;
    886 }
    887 
    888 DEFINE_SHOW_ATTRIBUTE(output_bpc);
    889 DEFINE_SHOW_ATTRIBUTE(vrr_range);
    890 
    891 static const struct file_operations dp_link_settings_debugfs_fops = {
    892 	.owner = THIS_MODULE,
    893 	.read = dp_link_settings_read,
    894 	.write = dp_link_settings_write,
    895 	.llseek = default_llseek
    896 };
    897 
    898 static const struct file_operations dp_phy_settings_debugfs_fop = {
    899 	.owner = THIS_MODULE,
    900 	.read = dp_phy_settings_read,
    901 	.write = dp_phy_settings_write,
    902 	.llseek = default_llseek
    903 };
    904 
    905 static const struct file_operations dp_phy_test_pattern_fops = {
    906 	.owner = THIS_MODULE,
    907 	.write = dp_phy_test_pattern_debugfs_write,
    908 	.llseek = default_llseek
    909 };
    910 
    911 static const struct file_operations sdp_message_fops = {
    912 	.owner = THIS_MODULE,
    913 	.write = dp_sdp_message_debugfs_write,
    914 	.llseek = default_llseek
    915 };
    916 
    917 static const struct file_operations dp_dpcd_address_debugfs_fops = {
    918 	.owner = THIS_MODULE,
    919 	.write = dp_dpcd_address_write,
    920 	.llseek = default_llseek
    921 };
    922 
    923 static const struct file_operations dp_dpcd_size_debugfs_fops = {
    924 	.owner = THIS_MODULE,
    925 	.write = dp_dpcd_size_write,
    926 	.llseek = default_llseek
    927 };
    928 
    929 static const struct file_operations dp_dpcd_data_debugfs_fops = {
    930 	.owner = THIS_MODULE,
    931 	.read = dp_dpcd_data_read,
    932 	.write = dp_dpcd_data_write,
    933 	.llseek = default_llseek
    934 };
    935 
    936 static const struct {
    937 	char *name;
    938 	const struct file_operations *fops;
    939 } dp_debugfs_entries[] = {
    940 		{"link_settings", &dp_link_settings_debugfs_fops},
    941 		{"phy_settings", &dp_phy_settings_debugfs_fop},
    942 		{"test_pattern", &dp_phy_test_pattern_fops},
    943 		{"output_bpc", &output_bpc_fops},
    944 		{"vrr_range", &vrr_range_fops},
    945 		{"sdp_message", &sdp_message_fops},
    946 		{"aux_dpcd_address", &dp_dpcd_address_debugfs_fops},
    947 		{"aux_dpcd_size", &dp_dpcd_size_debugfs_fops},
    948 		{"aux_dpcd_data", &dp_dpcd_data_debugfs_fops}
    949 };
    950 
    951 /*
    952  * Force YUV420 output if available from the given mode
    953  */
    954 static int force_yuv420_output_set(void *data, u64 val)
    955 {
    956 	struct amdgpu_dm_connector *connector = data;
    957 
    958 	connector->force_yuv420_output = (bool)val;
    959 
    960 	return 0;
    961 }
    962 
    963 /*
    964  * Check if YUV420 is forced when available from the given mode
    965  */
    966 static int force_yuv420_output_get(void *data, u64 *val)
    967 {
    968 	struct amdgpu_dm_connector *connector = data;
    969 
    970 	*val = connector->force_yuv420_output;
    971 
    972 	return 0;
    973 }
    974 
    975 DEFINE_DEBUGFS_ATTRIBUTE(force_yuv420_output_fops, force_yuv420_output_get,
    976 			 force_yuv420_output_set, "%llu\n");
    977 
    978 /*
    979  *  Read PSR state
    980  */
    981 static int psr_get(void *data, u64 *val)
    982 {
    983 	struct amdgpu_dm_connector *connector = data;
    984 	struct dc_link *link = connector->dc_link;
    985 	uint32_t psr_state = 0;
    986 
    987 	dc_link_get_psr_state(link, &psr_state);
    988 
    989 	*val = psr_state;
    990 
    991 	return 0;
    992 }
    993 
    994 
    995 DEFINE_DEBUGFS_ATTRIBUTE(psr_fops, psr_get, NULL, "%llu\n");
    996 
    997 void connector_debugfs_init(struct amdgpu_dm_connector *connector)
    998 {
    999 	int i;
   1000 	struct dentry *dir = connector->base.debugfs_entry;
   1001 
   1002 	if (connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
   1003 	    connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) {
   1004 		for (i = 0; i < ARRAY_SIZE(dp_debugfs_entries); i++) {
   1005 			debugfs_create_file(dp_debugfs_entries[i].name,
   1006 					    0644, dir, connector,
   1007 					    dp_debugfs_entries[i].fops);
   1008 		}
   1009 	}
   1010 	if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)
   1011 		debugfs_create_file_unsafe("psr_state", 0444, dir, connector, &psr_fops);
   1012 
   1013 	debugfs_create_file_unsafe("force_yuv420_output", 0644, dir, connector,
   1014 				   &force_yuv420_output_fops);
   1015 
   1016 }
   1017 
   1018 /*
   1019  * Writes DTN log state to the user supplied buffer.
   1020  * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_dtn_log
   1021  */
   1022 static ssize_t dtn_log_read(
   1023 	struct file *f,
   1024 	char __user *buf,
   1025 	size_t size,
   1026 	loff_t *pos)
   1027 {
   1028 	struct amdgpu_device *adev = file_inode(f)->i_private;
   1029 	struct dc *dc = adev->dm.dc;
   1030 	struct dc_log_buffer_ctx log_ctx = { 0 };
   1031 	ssize_t result = 0;
   1032 
   1033 	if (!buf || !size)
   1034 		return -EINVAL;
   1035 
   1036 	if (!dc->hwss.log_hw_state)
   1037 		return 0;
   1038 
   1039 	dc->hwss.log_hw_state(dc, &log_ctx);
   1040 
   1041 	if (*pos < log_ctx.pos) {
   1042 		size_t to_copy = log_ctx.pos - *pos;
   1043 
   1044 		to_copy = min(to_copy, size);
   1045 
   1046 		if (!copy_to_user(buf, log_ctx.buf + *pos, to_copy)) {
   1047 			*pos += to_copy;
   1048 			result = to_copy;
   1049 		}
   1050 	}
   1051 
   1052 	kfree(log_ctx.buf);
   1053 
   1054 	return result;
   1055 }
   1056 
   1057 /*
   1058  * Writes DTN log state to dmesg when triggered via a write.
   1059  * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dtn_log
   1060  */
   1061 static ssize_t dtn_log_write(
   1062 	struct file *f,
   1063 	const char __user *buf,
   1064 	size_t size,
   1065 	loff_t *pos)
   1066 {
   1067 	struct amdgpu_device *adev = file_inode(f)->i_private;
   1068 	struct dc *dc = adev->dm.dc;
   1069 
   1070 	/* Write triggers log output via dmesg. */
   1071 	if (size == 0)
   1072 		return 0;
   1073 
   1074 	if (dc->hwss.log_hw_state)
   1075 		dc->hwss.log_hw_state(dc, NULL);
   1076 
   1077 	return size;
   1078 }
   1079 
   1080 /*
   1081  * Backlight at this moment.  Read only.
   1082  * As written to display, taking ABM and backlight lut into account.
   1083  * Ranges from 0x0 to 0x10000 (= 100% PWM)
   1084  */
   1085 static int current_backlight_read(struct seq_file *m, void *data)
   1086 {
   1087 	struct drm_info_node *node = (struct drm_info_node *)m->private;
   1088 	struct drm_device *dev = node->minor->dev;
   1089 	struct amdgpu_device *adev = dev->dev_private;
   1090 	struct dc *dc = adev->dm.dc;
   1091 	unsigned int backlight = dc_get_current_backlight_pwm(dc);
   1092 
   1093 	seq_printf(m, "0x%x\n", backlight);
   1094 	return 0;
   1095 }
   1096 
   1097 /*
   1098  * Backlight value that is being approached.  Read only.
   1099  * As written to display, taking ABM and backlight lut into account.
   1100  * Ranges from 0x0 to 0x10000 (= 100% PWM)
   1101  */
   1102 static int target_backlight_read(struct seq_file *m, void *data)
   1103 {
   1104 	struct drm_info_node *node = (struct drm_info_node *)m->private;
   1105 	struct drm_device *dev = node->minor->dev;
   1106 	struct amdgpu_device *adev = dev->dev_private;
   1107 	struct dc *dc = adev->dm.dc;
   1108 	unsigned int backlight = dc_get_target_backlight_pwm(dc);
   1109 
   1110 	seq_printf(m, "0x%x\n", backlight);
   1111 	return 0;
   1112 }
   1113 
   1114 static int mst_topo(struct seq_file *m, void *unused)
   1115 {
   1116 	struct drm_info_node *node = (struct drm_info_node *)m->private;
   1117 	struct drm_device *dev = node->minor->dev;
   1118 	struct drm_connector *connector;
   1119 	struct drm_connector_list_iter conn_iter;
   1120 	struct amdgpu_dm_connector *aconnector;
   1121 
   1122 	drm_connector_list_iter_begin(dev, &conn_iter);
   1123 	drm_for_each_connector_iter(connector, &conn_iter) {
   1124 		if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
   1125 			continue;
   1126 
   1127 		aconnector = to_amdgpu_dm_connector(connector);
   1128 
   1129 		seq_printf(m, "\nMST topology for connector %d\n", aconnector->connector_id);
   1130 		drm_dp_mst_dump_topology(m, &aconnector->mst_mgr);
   1131 	}
   1132 	drm_connector_list_iter_end(&conn_iter);
   1133 
   1134 	return 0;
   1135 }
   1136 
   1137 static const struct drm_info_list amdgpu_dm_debugfs_list[] = {
   1138 	{"amdgpu_current_backlight_pwm", &current_backlight_read},
   1139 	{"amdgpu_target_backlight_pwm", &target_backlight_read},
   1140 	{"amdgpu_mst_topology", &mst_topo},
   1141 };
   1142 
   1143 /*
   1144  * Sets the DC visual confirm debug option from the given string.
   1145  * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_visual_confirm
   1146  */
   1147 static int visual_confirm_set(void *data, u64 val)
   1148 {
   1149 	struct amdgpu_device *adev = data;
   1150 
   1151 	adev->dm.dc->debug.visual_confirm = (enum visual_confirm)val;
   1152 
   1153 	return 0;
   1154 }
   1155 
   1156 /*
   1157  * Reads the DC visual confirm debug option value into the given buffer.
   1158  * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_visual_confirm
   1159  */
   1160 static int visual_confirm_get(void *data, u64 *val)
   1161 {
   1162 	struct amdgpu_device *adev = data;
   1163 
   1164 	*val = adev->dm.dc->debug.visual_confirm;
   1165 
   1166 	return 0;
   1167 }
   1168 
   1169 DEFINE_DEBUGFS_ATTRIBUTE(visual_confirm_fops, visual_confirm_get,
   1170 			 visual_confirm_set, "%llu\n");
   1171 
   1172 int dtn_debugfs_init(struct amdgpu_device *adev)
   1173 {
   1174 	static const struct file_operations dtn_log_fops = {
   1175 		.owner = THIS_MODULE,
   1176 		.read = dtn_log_read,
   1177 		.write = dtn_log_write,
   1178 		.llseek = default_llseek
   1179 	};
   1180 
   1181 	struct drm_minor *minor = adev->ddev->primary;
   1182 	struct dentry *root = minor->debugfs_root;
   1183 	int ret;
   1184 
   1185 	ret = amdgpu_debugfs_add_files(adev, amdgpu_dm_debugfs_list,
   1186 				ARRAY_SIZE(amdgpu_dm_debugfs_list));
   1187 	if (ret)
   1188 		return ret;
   1189 
   1190 	debugfs_create_file("amdgpu_dm_dtn_log", 0644, root, adev,
   1191 			    &dtn_log_fops);
   1192 
   1193 	debugfs_create_file_unsafe("amdgpu_dm_visual_confirm", 0644, root, adev,
   1194 				   &visual_confirm_fops);
   1195 
   1196 	return 0;
   1197 }
   1198