2 * Copyright 2018 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * 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 OR
20 * OTHER DEALINGS IN THE SOFTWARE.
26 #include <linux/uaccess.h>
28 #include <drm/drm_debugfs.h>
32 #include "amdgpu_dm.h"
33 #include "amdgpu_dm_debugfs.h"
34 #include "dm_helpers.h"
36 /* function description
37 * get/ set DP configuration: lane_count, link_rate, spread_spectrum
39 * valid lane count value: 1, 2, 4
40 * valid link rate value:
41 * 06h = 1.62Gbps per lane
42 * 0Ah = 2.7Gbps per lane
43 * 0Ch = 3.24Gbps per lane
44 * 14h = 5.4Gbps per lane
45 * 1Eh = 8.1Gbps per lane
47 * debugfs is located at /sys/kernel/debug/dri/0/DP-x/link_settings
49 * --- to get dp configuration
53 * It will list current, verified, reported, preferred dp configuration.
54 * current -- for current video mode
55 * verified --- maximum configuration which pass link training
56 * reported --- DP rx report caps (DPCD register offset 0, 1 2)
57 * preferred --- user force settings
59 * --- set (or force) dp configuration
61 * echo <lane_count> <link_rate> > link_settings
63 * for example, to force to 2 lane, 2.7GHz,
64 * echo 4 0xa > link_settings
66 * spread_spectrum could not be changed dynamically.
68 * in case invalid lane count, link rate are force, no hw programming will be
69 * done. please check link settings after force operation to see if HW get
74 * check current and preferred settings.
77 static ssize_t
dp_link_settings_read(struct file
*f
, char __user
*buf
,
78 size_t size
, loff_t
*pos
)
80 struct amdgpu_dm_connector
*connector
= file_inode(f
)->i_private
;
81 struct dc_link
*link
= connector
->dc_link
;
83 char *rd_buf_ptr
= NULL
;
84 const uint32_t rd_buf_size
= 100;
89 if (*pos
& 3 || size
& 3)
92 rd_buf
= kcalloc(rd_buf_size
, sizeof(char), GFP_KERNEL
);
98 str_len
= strlen("Current: %d %d %d ");
99 snprintf(rd_buf_ptr
, str_len
, "Current: %d %d %d ",
100 link
->cur_link_settings
.lane_count
,
101 link
->cur_link_settings
.link_rate
,
102 link
->cur_link_settings
.link_spread
);
103 rd_buf_ptr
+= str_len
;
105 str_len
= strlen("Verified: %d %d %d ");
106 snprintf(rd_buf_ptr
, str_len
, "Verified: %d %d %d ",
107 link
->verified_link_cap
.lane_count
,
108 link
->verified_link_cap
.link_rate
,
109 link
->verified_link_cap
.link_spread
);
110 rd_buf_ptr
+= str_len
;
112 str_len
= strlen("Reported: %d %d %d ");
113 snprintf(rd_buf_ptr
, str_len
, "Reported: %d %d %d ",
114 link
->reported_link_cap
.lane_count
,
115 link
->reported_link_cap
.link_rate
,
116 link
->reported_link_cap
.link_spread
);
117 rd_buf_ptr
+= str_len
;
119 str_len
= strlen("Preferred: %d %d %d ");
120 snprintf(rd_buf_ptr
, str_len
, "Preferred: %d %d %d\n",
121 link
->preferred_link_setting
.lane_count
,
122 link
->preferred_link_setting
.link_rate
,
123 link
->preferred_link_setting
.link_spread
);
126 if (*pos
>= rd_buf_size
)
129 r
= put_user(*(rd_buf
+ result
), buf
);
131 return r
; /* r = -EFAULT */
143 static ssize_t
dp_link_settings_write(struct file
*f
, const char __user
*buf
,
144 size_t size
, loff_t
*pos
)
146 struct amdgpu_dm_connector
*connector
= file_inode(f
)->i_private
;
147 struct dc_link
*link
= connector
->dc_link
;
148 struct dc
*dc
= (struct dc
*)link
->dc
;
149 struct dc_link_settings prefer_link_settings
;
151 char *wr_buf_ptr
= NULL
;
152 const uint32_t wr_buf_size
= 40;
156 /* 0: lane_count; 1: link_rate */
157 uint8_t param_index
= 0;
159 const char delimiter
[3] = {' ', '\n', '\0'};
160 bool valid_input
= false;
165 wr_buf
= kcalloc(wr_buf_size
, sizeof(char), GFP_KERNEL
);
170 r
= copy_from_user(wr_buf_ptr
, buf
, wr_buf_size
);
172 /* r is bytes not be copied */
173 if (r
>= wr_buf_size
) {
175 DRM_DEBUG_DRIVER("user data not read\n");
179 bytes_from_user
= wr_buf_size
- r
;
181 while (isspace(*wr_buf_ptr
))
184 while ((*wr_buf_ptr
!= '\0') && (param_index
< 2)) {
186 sub_str
= strsep(&wr_buf_ptr
, delimiter
);
188 r
= kstrtol(sub_str
, 16, ¶m
[param_index
]);
191 DRM_DEBUG_DRIVER("string to int convert error code: %d\n", r
);
194 while (isspace(*wr_buf_ptr
))
201 case LANE_COUNT_FOUR
:
212 case LINK_RATE_HIGH2
:
213 case LINK_RATE_HIGH3
:
222 DRM_DEBUG_DRIVER("Invalid Input value No HW will be programmed\n");
223 return bytes_from_user
;
226 /* save user force lane_count, link_rate to preferred settings
227 * spread spectrum will not be changed
229 prefer_link_settings
.link_spread
= link
->cur_link_settings
.link_spread
;
230 prefer_link_settings
.lane_count
= param
[0];
231 prefer_link_settings
.link_rate
= param
[1];
233 dc_link_set_preferred_link_settings(dc
, &prefer_link_settings
, link
);
236 return bytes_from_user
;
239 /* function: get current DP PHY settings: voltage swing, pre-emphasis,
240 * post-cursor2 (defined by VESA DP specification)
243 * voltage swing: 0,1,2,3
244 * pre-emphasis : 0,1,2,3
245 * post cursor2 : 0,1,2,3
248 * how to use this debugfs
250 * debugfs is located at /sys/kernel/debug/dri/0/DP-x
252 * there will be directories, like DP-1, DP-2,DP-3, etc. for DP display
254 * To figure out which DP-x is the display for DP to be check,
257 * There should be debugfs file, like link_settings, phy_settings.
259 * from lane_count, link_rate to figure which DP-x is for display to be worked
262 * To get current DP PHY settings,
265 * To change DP PHY settings,
266 * echo <voltage_swing> <pre-emphasis> <post_cursor2> > phy_settings
267 * for examle, to change voltage swing to 2, pre-emphasis to 3, post_cursor2 to
269 * echo 2 3 0 > phy_settings
271 * To check if change be applied, get current phy settings by
274 * In case invalid values are set by user, like
275 * echo 1 4 0 > phy_settings
277 * HW will NOT be programmed by these settings.
278 * cat phy_settings will show the previous valid settings.
280 static ssize_t
dp_phy_settings_read(struct file
*f
, char __user
*buf
,
281 size_t size
, loff_t
*pos
)
283 struct amdgpu_dm_connector
*connector
= file_inode(f
)->i_private
;
284 struct dc_link
*link
= connector
->dc_link
;
286 const uint32_t rd_buf_size
= 20;
290 if (*pos
& 3 || size
& 3)
293 rd_buf
= kcalloc(rd_buf_size
, sizeof(char), GFP_KERNEL
);
297 snprintf(rd_buf
, rd_buf_size
, " %d %d %d ",
298 link
->cur_lane_setting
.VOLTAGE_SWING
,
299 link
->cur_lane_setting
.PRE_EMPHASIS
,
300 link
->cur_lane_setting
.POST_CURSOR2
);
303 if (*pos
>= rd_buf_size
)
306 r
= put_user((*(rd_buf
+ result
)), buf
);
308 return r
; /* r = -EFAULT */
320 static ssize_t
dp_phy_settings_write(struct file
*f
, const char __user
*buf
,
321 size_t size
, loff_t
*pos
)
323 struct amdgpu_dm_connector
*connector
= file_inode(f
)->i_private
;
324 struct dc_link
*link
= connector
->dc_link
;
325 struct dc
*dc
= (struct dc
*)link
->dc
;
327 char *wr_buf_ptr
= NULL
;
328 uint32_t wr_buf_size
= 40;
332 uint8_t param_index
= 0;
334 const char delimiter
[3] = {' ', '\n', '\0'};
335 bool use_prefer_link_setting
;
336 struct link_training_settings link_lane_settings
;
341 wr_buf
= kcalloc(wr_buf_size
, sizeof(char), GFP_KERNEL
);
346 r
= copy_from_user(wr_buf_ptr
, buf
, wr_buf_size
);
348 /* r is bytes not be copied */
349 if (r
>= wr_buf_size
) {
351 DRM_DEBUG_DRIVER("user data not be read\n");
355 bytes_from_user
= wr_buf_size
- r
;
357 while (isspace(*wr_buf_ptr
))
360 while ((*wr_buf_ptr
!= '\0') && (param_index
< 3)) {
362 sub_str
= strsep(&wr_buf_ptr
, delimiter
);
364 r
= kstrtol(sub_str
, 16, ¶m
[param_index
]);
367 DRM_DEBUG_DRIVER("string to int convert error code: %d\n", r
);
370 while (isspace(*wr_buf_ptr
))
374 if ((param
[0] > VOLTAGE_SWING_MAX_LEVEL
) ||
375 (param
[1] > PRE_EMPHASIS_MAX_LEVEL
) ||
376 (param
[2] > POST_CURSOR2_MAX_LEVEL
)) {
378 DRM_DEBUG_DRIVER("Invalid Input No HW will be programmed\n");
379 return bytes_from_user
;
382 /* get link settings: lane count, link rate */
383 use_prefer_link_setting
=
384 ((link
->preferred_link_setting
.link_rate
!= LINK_RATE_UNKNOWN
) &&
385 (link
->test_pattern_enabled
));
387 memset(&link_lane_settings
, 0, sizeof(link_lane_settings
));
389 if (use_prefer_link_setting
) {
390 link_lane_settings
.link_settings
.lane_count
=
391 link
->preferred_link_setting
.lane_count
;
392 link_lane_settings
.link_settings
.link_rate
=
393 link
->preferred_link_setting
.link_rate
;
394 link_lane_settings
.link_settings
.link_spread
=
395 link
->preferred_link_setting
.link_spread
;
397 link_lane_settings
.link_settings
.lane_count
=
398 link
->cur_link_settings
.lane_count
;
399 link_lane_settings
.link_settings
.link_rate
=
400 link
->cur_link_settings
.link_rate
;
401 link_lane_settings
.link_settings
.link_spread
=
402 link
->cur_link_settings
.link_spread
;
405 /* apply phy settings from user */
406 for (r
= 0; r
< link_lane_settings
.link_settings
.lane_count
; r
++) {
407 link_lane_settings
.lane_settings
[r
].VOLTAGE_SWING
=
408 (enum dc_voltage_swing
) (param
[0]);
409 link_lane_settings
.lane_settings
[r
].PRE_EMPHASIS
=
410 (enum dc_pre_emphasis
) (param
[1]);
411 link_lane_settings
.lane_settings
[r
].POST_CURSOR2
=
412 (enum dc_post_cursor2
) (param
[2]);
415 /* program ASIC registers and DPCD registers */
416 dc_link_set_drive_settings(dc
, &link_lane_settings
, link
);
419 return bytes_from_user
;
422 /* function description
424 * set PHY layer or Link layer test pattern
425 * PHY test pattern is used for PHY SI check.
426 * Link layer test will not affect PHY SI.
428 * Reset Test Pattern:
429 * 0 = DP_TEST_PATTERN_VIDEO_MODE
431 * PHY test pattern supported:
432 * 1 = DP_TEST_PATTERN_D102
433 * 2 = DP_TEST_PATTERN_SYMBOL_ERROR
434 * 3 = DP_TEST_PATTERN_PRBS7
435 * 4 = DP_TEST_PATTERN_80BIT_CUSTOM
436 * 5 = DP_TEST_PATTERN_CP2520_1
437 * 6 = DP_TEST_PATTERN_CP2520_2 = DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE
438 * 7 = DP_TEST_PATTERN_CP2520_3
440 * DP PHY Link Training Patterns
441 * 8 = DP_TEST_PATTERN_TRAINING_PATTERN1
442 * 9 = DP_TEST_PATTERN_TRAINING_PATTERN2
443 * a = DP_TEST_PATTERN_TRAINING_PATTERN3
444 * b = DP_TEST_PATTERN_TRAINING_PATTERN4
446 * DP Link Layer Test pattern
447 * c = DP_TEST_PATTERN_COLOR_SQUARES
448 * d = DP_TEST_PATTERN_COLOR_SQUARES_CEA
449 * e = DP_TEST_PATTERN_VERTICAL_BARS
450 * f = DP_TEST_PATTERN_HORIZONTAL_BARS
451 * 10= DP_TEST_PATTERN_COLOR_RAMP
453 * debugfs phy_test_pattern is located at /syskernel/debug/dri/0/DP-x
455 * --- set test pattern
456 * echo <test pattern #> > test_pattern
458 * If test pattern # is not supported, NO HW programming will be done.
459 * for DP_TEST_PATTERN_80BIT_CUSTOM, it needs extra 10 bytes of data
460 * for the user pattern. input 10 bytes data are separated by space
462 * echo 0x4 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x99 0xaa > test_pattern
464 * --- reset test pattern
465 * echo 0 > test_pattern
467 * --- HPD detection is disabled when set PHY test pattern
469 * when PHY test pattern (pattern # within [1,7]) is set, HPD pin of HW ASIC
470 * is disable. User could unplug DP display from DP connected and plug scope to
471 * check test pattern PHY SI.
472 * If there is need unplug scope and plug DP display back, do steps below:
473 * echo 0 > phy_test_pattern
477 * "echo 0 > phy_test_pattern" will re-enable HPD pin again so that video sw
478 * driver could detect "unplug scope" and "plug DP display"
480 static ssize_t
dp_phy_test_pattern_debugfs_write(struct file
*f
, const char __user
*buf
,
481 size_t size
, loff_t
*pos
)
483 struct amdgpu_dm_connector
*connector
= file_inode(f
)->i_private
;
484 struct dc_link
*link
= connector
->dc_link
;
486 char *wr_buf_ptr
= NULL
;
487 uint32_t wr_buf_size
= 100;
488 uint32_t wr_buf_count
= 0;
491 char *sub_str
= NULL
;
492 uint8_t param_index
= 0;
493 uint8_t param_nums
= 0;
494 long param
[11] = {0x0};
495 const char delimiter
[3] = {' ', '\n', '\0'};
496 enum dp_test_pattern test_pattern
= DP_TEST_PATTERN_UNSUPPORTED
;
497 bool disable_hpd
= false;
498 bool valid_test_pattern
= false;
499 /* init with defalut 80bit custom pattern */
500 uint8_t custom_pattern
[10] = {
501 0x1f, 0x7c, 0xf0, 0xc1, 0x07,
502 0x1f, 0x7c, 0xf0, 0xc1, 0x07
504 struct dc_link_settings prefer_link_settings
= {LANE_COUNT_UNKNOWN
,
505 LINK_RATE_UNKNOWN
, LINK_SPREAD_DISABLED
};
506 struct dc_link_settings cur_link_settings
= {LANE_COUNT_UNKNOWN
,
507 LINK_RATE_UNKNOWN
, LINK_SPREAD_DISABLED
};
508 struct link_training_settings link_training_settings
;
514 wr_buf
= kcalloc(wr_buf_size
, sizeof(char), GFP_KERNEL
);
519 r
= copy_from_user(wr_buf_ptr
, buf
, wr_buf_size
);
521 /* r is bytes not be copied */
522 if (r
>= wr_buf_size
) {
524 DRM_DEBUG_DRIVER("user data not be read\n");
528 bytes_from_user
= wr_buf_size
- r
;
530 /* check number of parameters. isspace could not differ space and \n */
531 while ((*wr_buf_ptr
!= 0xa) && (wr_buf_count
< wr_buf_size
)) {
533 while (isspace(*wr_buf_ptr
) && (wr_buf_count
< wr_buf_size
)) {
538 if (wr_buf_count
== wr_buf_size
)
542 while ((!isspace(*wr_buf_ptr
)) && (wr_buf_count
< wr_buf_size
)) {
549 if (wr_buf_count
== wr_buf_size
)
553 /* max 11 parameters */
557 wr_buf_ptr
= wr_buf
; /* reset buf pinter */
558 wr_buf_count
= 0; /* number of char already checked */
560 while (isspace(*wr_buf_ptr
) && (wr_buf_count
< wr_buf_size
)) {
565 while (param_index
< param_nums
) {
566 /* after strsep, wr_buf_ptr will be moved to after space */
567 sub_str
= strsep(&wr_buf_ptr
, delimiter
);
569 r
= kstrtol(sub_str
, 16, ¶m
[param_index
]);
572 DRM_DEBUG_DRIVER("string to int convert error code: %d\n", r
);
577 test_pattern
= param
[0];
579 switch (test_pattern
) {
580 case DP_TEST_PATTERN_VIDEO_MODE
:
581 case DP_TEST_PATTERN_COLOR_SQUARES
:
582 case DP_TEST_PATTERN_COLOR_SQUARES_CEA
:
583 case DP_TEST_PATTERN_VERTICAL_BARS
:
584 case DP_TEST_PATTERN_HORIZONTAL_BARS
:
585 case DP_TEST_PATTERN_COLOR_RAMP
:
586 valid_test_pattern
= true;
589 case DP_TEST_PATTERN_D102
:
590 case DP_TEST_PATTERN_SYMBOL_ERROR
:
591 case DP_TEST_PATTERN_PRBS7
:
592 case DP_TEST_PATTERN_80BIT_CUSTOM
:
593 case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE
:
594 case DP_TEST_PATTERN_TRAINING_PATTERN4
:
596 valid_test_pattern
= true;
600 valid_test_pattern
= false;
601 test_pattern
= DP_TEST_PATTERN_UNSUPPORTED
;
605 if (!valid_test_pattern
) {
607 DRM_DEBUG_DRIVER("Invalid Test Pattern Parameters\n");
608 return bytes_from_user
;
611 if (test_pattern
== DP_TEST_PATTERN_80BIT_CUSTOM
) {
612 for (i
= 0; i
< 10; i
++) {
613 if ((uint8_t) param
[i
+ 1] != 0x0)
618 /* not use default value */
619 for (i
= 0; i
< 10; i
++)
620 custom_pattern
[i
] = (uint8_t) param
[i
+ 1];
624 /* Usage: set DP physical test pattern using debugfs with normal DP
625 * panel. Then plug out DP panel and connect a scope to measure
626 * For normal video mode and test pattern generated from CRCT,
627 * they are visibile to user. So do not disable HPD.
628 * Video Mode is also set to clear the test pattern, so enable HPD
629 * because it might have been disabled after a test pattern was set.
630 * AUX depends on HPD * sequence dependent, do not move!
633 dc_link_enable_hpd(link
);
635 prefer_link_settings
.lane_count
= link
->verified_link_cap
.lane_count
;
636 prefer_link_settings
.link_rate
= link
->verified_link_cap
.link_rate
;
637 prefer_link_settings
.link_spread
= link
->verified_link_cap
.link_spread
;
639 cur_link_settings
.lane_count
= link
->cur_link_settings
.lane_count
;
640 cur_link_settings
.link_rate
= link
->cur_link_settings
.link_rate
;
641 cur_link_settings
.link_spread
= link
->cur_link_settings
.link_spread
;
643 link_training_settings
.link_settings
= cur_link_settings
;
646 if (test_pattern
!= DP_TEST_PATTERN_VIDEO_MODE
) {
647 if (prefer_link_settings
.lane_count
!= LANE_COUNT_UNKNOWN
&&
648 prefer_link_settings
.link_rate
!= LINK_RATE_UNKNOWN
&&
649 (prefer_link_settings
.lane_count
!= cur_link_settings
.lane_count
||
650 prefer_link_settings
.link_rate
!= cur_link_settings
.link_rate
))
651 link_training_settings
.link_settings
= prefer_link_settings
;
654 for (i
= 0; i
< (unsigned int)(link_training_settings
.link_settings
.lane_count
); i
++)
655 link_training_settings
.lane_settings
[i
] = link
->cur_lane_setting
;
657 dc_link_set_test_pattern(
660 DP_TEST_PATTERN_COLOR_SPACE_RGB
,
661 &link_training_settings
,
665 /* Usage: Set DP physical test pattern using AMDDP with normal DP panel
666 * Then plug out DP panel and connect a scope to measure DP PHY signal.
667 * Need disable interrupt to avoid SW driver disable DP output. This is
668 * done after the test pattern is set.
670 if (valid_test_pattern
&& disable_hpd
)
671 dc_link_disable_hpd(link
);
675 return bytes_from_user
;
679 * Returns the current and maximum output bpc for the connector.
680 * Example usage: cat /sys/kernel/debug/dri/0/DP-1/output_bpc
682 static int output_bpc_show(struct seq_file
*m
, void *data
)
684 struct drm_connector
*connector
= m
->private;
685 struct drm_device
*dev
= connector
->dev
;
686 struct drm_crtc
*crtc
= NULL
;
687 struct dm_crtc_state
*dm_crtc_state
= NULL
;
691 mutex_lock(&dev
->mode_config
.mutex
);
692 drm_modeset_lock(&dev
->mode_config
.connection_mutex
, NULL
);
694 if (connector
->state
== NULL
)
697 crtc
= connector
->state
->crtc
;
701 drm_modeset_lock(&crtc
->mutex
, NULL
);
702 if (crtc
->state
== NULL
)
705 dm_crtc_state
= to_dm_crtc_state(crtc
->state
);
706 if (dm_crtc_state
->stream
== NULL
)
709 switch (dm_crtc_state
->stream
->timing
.display_color_depth
) {
710 case COLOR_DEPTH_666
:
713 case COLOR_DEPTH_888
:
716 case COLOR_DEPTH_101010
:
719 case COLOR_DEPTH_121212
:
722 case COLOR_DEPTH_161616
:
729 seq_printf(m
, "Current: %u\n", bpc
);
730 seq_printf(m
, "Maximum: %u\n", connector
->display_info
.bpc
);
735 drm_modeset_unlock(&crtc
->mutex
);
737 drm_modeset_unlock(&dev
->mode_config
.connection_mutex
);
738 mutex_unlock(&dev
->mode_config
.mutex
);
744 * Returns the min and max vrr vfreq through the connector's debugfs file.
745 * Example usage: cat /sys/kernel/debug/dri/0/DP-1/vrr_range
747 static int vrr_range_show(struct seq_file
*m
, void *data
)
749 struct drm_connector
*connector
= m
->private;
750 struct amdgpu_dm_connector
*aconnector
= to_amdgpu_dm_connector(connector
);
752 if (connector
->status
!= connector_status_connected
)
755 seq_printf(m
, "Min: %u\n", (unsigned int)aconnector
->min_vfreq
);
756 seq_printf(m
, "Max: %u\n", (unsigned int)aconnector
->max_vfreq
);
761 /* function description
763 * generic SDP message access for testing
765 * debugfs sdp_message is located at /syskernel/debug/dri/0/DP-x
768 * Hb0 : Secondary-Data Packet ID
769 * Hb1 : Secondary-Data Packet type
770 * Hb2 : Secondary-Data-packet-specific header, Byte 0
771 * Hb3 : Secondary-Data-packet-specific header, Byte 1
773 * for using custom sdp message: input 4 bytes SDP header and 32 bytes raw data
775 static ssize_t
dp_sdp_message_debugfs_write(struct file
*f
, const char __user
*buf
,
776 size_t size
, loff_t
*pos
)
780 struct amdgpu_dm_connector
*connector
= file_inode(f
)->i_private
;
781 struct dm_crtc_state
*acrtc_state
;
782 uint32_t write_size
= 36;
784 if (connector
->base
.status
!= connector_status_connected
)
790 acrtc_state
= to_dm_crtc_state(connector
->base
.state
->crtc
->state
);
792 r
= copy_from_user(data
, buf
, write_size
);
796 dc_stream_send_dp_sdp(acrtc_state
->stream
, data
, write_size
);
801 static ssize_t
dp_dpcd_address_write(struct file
*f
, const char __user
*buf
,
802 size_t size
, loff_t
*pos
)
805 struct amdgpu_dm_connector
*connector
= file_inode(f
)->i_private
;
807 if (size
< sizeof(connector
->debugfs_dpcd_address
))
810 r
= copy_from_user(&connector
->debugfs_dpcd_address
,
811 buf
, sizeof(connector
->debugfs_dpcd_address
));
816 static ssize_t
dp_dpcd_size_write(struct file
*f
, const char __user
*buf
,
817 size_t size
, loff_t
*pos
)
820 struct amdgpu_dm_connector
*connector
= file_inode(f
)->i_private
;
822 if (size
< sizeof(connector
->debugfs_dpcd_size
))
825 r
= copy_from_user(&connector
->debugfs_dpcd_size
,
826 buf
, sizeof(connector
->debugfs_dpcd_size
));
828 if (connector
->debugfs_dpcd_size
> 256)
829 connector
->debugfs_dpcd_size
= 0;
834 static ssize_t
dp_dpcd_data_write(struct file
*f
, const char __user
*buf
,
835 size_t size
, loff_t
*pos
)
839 struct amdgpu_dm_connector
*connector
= file_inode(f
)->i_private
;
840 struct dc_link
*link
= connector
->dc_link
;
841 uint32_t write_size
= connector
->debugfs_dpcd_size
;
843 if (size
< write_size
)
846 data
= kzalloc(write_size
, GFP_KERNEL
);
850 r
= copy_from_user(data
, buf
, write_size
);
852 dm_helpers_dp_write_dpcd(link
->ctx
, link
,
853 connector
->debugfs_dpcd_address
, data
, write_size
- r
);
855 return write_size
- r
;
858 static ssize_t
dp_dpcd_data_read(struct file
*f
, char __user
*buf
,
859 size_t size
, loff_t
*pos
)
863 struct amdgpu_dm_connector
*connector
= file_inode(f
)->i_private
;
864 struct dc_link
*link
= connector
->dc_link
;
865 uint32_t read_size
= connector
->debugfs_dpcd_size
;
867 if (size
< read_size
)
870 data
= kzalloc(read_size
, GFP_KERNEL
);
874 dm_helpers_dp_read_dpcd(link
->ctx
, link
,
875 connector
->debugfs_dpcd_address
, data
, read_size
);
877 r
= copy_to_user(buf
, data
, read_size
);
880 return read_size
- r
;
883 DEFINE_SHOW_ATTRIBUTE(output_bpc
);
884 DEFINE_SHOW_ATTRIBUTE(vrr_range
);
886 static const struct file_operations dp_link_settings_debugfs_fops
= {
887 .owner
= THIS_MODULE
,
888 .read
= dp_link_settings_read
,
889 .write
= dp_link_settings_write
,
890 .llseek
= default_llseek
893 static const struct file_operations dp_phy_settings_debugfs_fop
= {
894 .owner
= THIS_MODULE
,
895 .read
= dp_phy_settings_read
,
896 .write
= dp_phy_settings_write
,
897 .llseek
= default_llseek
900 static const struct file_operations dp_phy_test_pattern_fops
= {
901 .owner
= THIS_MODULE
,
902 .write
= dp_phy_test_pattern_debugfs_write
,
903 .llseek
= default_llseek
906 static const struct file_operations sdp_message_fops
= {
907 .owner
= THIS_MODULE
,
908 .write
= dp_sdp_message_debugfs_write
,
909 .llseek
= default_llseek
912 static const struct file_operations dp_dpcd_address_debugfs_fops
= {
913 .owner
= THIS_MODULE
,
914 .write
= dp_dpcd_address_write
,
915 .llseek
= default_llseek
918 static const struct file_operations dp_dpcd_size_debugfs_fops
= {
919 .owner
= THIS_MODULE
,
920 .write
= dp_dpcd_size_write
,
921 .llseek
= default_llseek
924 static const struct file_operations dp_dpcd_data_debugfs_fops
= {
925 .owner
= THIS_MODULE
,
926 .read
= dp_dpcd_data_read
,
927 .write
= dp_dpcd_data_write
,
928 .llseek
= default_llseek
931 static const struct {
933 const struct file_operations
*fops
;
934 } dp_debugfs_entries
[] = {
935 {"link_settings", &dp_link_settings_debugfs_fops
},
936 {"phy_settings", &dp_phy_settings_debugfs_fop
},
937 {"test_pattern", &dp_phy_test_pattern_fops
},
938 {"output_bpc", &output_bpc_fops
},
939 {"vrr_range", &vrr_range_fops
},
940 {"sdp_message", &sdp_message_fops
},
941 {"aux_dpcd_address", &dp_dpcd_address_debugfs_fops
},
942 {"aux_dpcd_size", &dp_dpcd_size_debugfs_fops
},
943 {"aux_dpcd_data", &dp_dpcd_data_debugfs_fops
}
947 * Force YUV420 output if available from the given mode
949 static int force_yuv420_output_set(void *data
, u64 val
)
951 struct amdgpu_dm_connector
*connector
= data
;
953 connector
->force_yuv420_output
= (bool)val
;
959 * Check if YUV420 is forced when available from the given mode
961 static int force_yuv420_output_get(void *data
, u64
*val
)
963 struct amdgpu_dm_connector
*connector
= data
;
965 *val
= connector
->force_yuv420_output
;
970 DEFINE_DEBUGFS_ATTRIBUTE(force_yuv420_output_fops
, force_yuv420_output_get
,
971 force_yuv420_output_set
, "%llu\n");
976 static int psr_get(void *data
, u64
*val
)
978 struct amdgpu_dm_connector
*connector
= data
;
979 struct dc_link
*link
= connector
->dc_link
;
980 uint32_t psr_state
= 0;
982 dc_link_get_psr_state(link
, &psr_state
);
990 DEFINE_DEBUGFS_ATTRIBUTE(psr_fops
, psr_get
, NULL
, "%llu\n");
992 void connector_debugfs_init(struct amdgpu_dm_connector
*connector
)
995 struct dentry
*dir
= connector
->base
.debugfs_entry
;
997 if (connector
->base
.connector_type
== DRM_MODE_CONNECTOR_DisplayPort
||
998 connector
->base
.connector_type
== DRM_MODE_CONNECTOR_eDP
) {
999 for (i
= 0; i
< ARRAY_SIZE(dp_debugfs_entries
); i
++) {
1000 debugfs_create_file(dp_debugfs_entries
[i
].name
,
1001 0644, dir
, connector
,
1002 dp_debugfs_entries
[i
].fops
);
1005 if (connector
->base
.connector_type
== DRM_MODE_CONNECTOR_eDP
)
1006 debugfs_create_file_unsafe("psr_state", 0444, dir
, connector
, &psr_fops
);
1008 debugfs_create_file_unsafe("force_yuv420_output", 0644, dir
, connector
,
1009 &force_yuv420_output_fops
);
1014 * Writes DTN log state to the user supplied buffer.
1015 * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_dtn_log
1017 static ssize_t
dtn_log_read(
1023 struct amdgpu_device
*adev
= file_inode(f
)->i_private
;
1024 struct dc
*dc
= adev
->dm
.dc
;
1025 struct dc_log_buffer_ctx log_ctx
= { 0 };
1031 if (!dc
->hwss
.log_hw_state
)
1034 dc
->hwss
.log_hw_state(dc
, &log_ctx
);
1036 if (*pos
< log_ctx
.pos
) {
1037 size_t to_copy
= log_ctx
.pos
- *pos
;
1039 to_copy
= min(to_copy
, size
);
1041 if (!copy_to_user(buf
, log_ctx
.buf
+ *pos
, to_copy
)) {
1053 * Writes DTN log state to dmesg when triggered via a write.
1054 * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dtn_log
1056 static ssize_t
dtn_log_write(
1058 const char __user
*buf
,
1062 struct amdgpu_device
*adev
= file_inode(f
)->i_private
;
1063 struct dc
*dc
= adev
->dm
.dc
;
1065 /* Write triggers log output via dmesg. */
1069 if (dc
->hwss
.log_hw_state
)
1070 dc
->hwss
.log_hw_state(dc
, NULL
);
1076 * Backlight at this moment. Read only.
1077 * As written to display, taking ABM and backlight lut into account.
1078 * Ranges from 0x0 to 0x10000 (= 100% PWM)
1080 static int current_backlight_read(struct seq_file
*m
, void *data
)
1082 struct drm_info_node
*node
= (struct drm_info_node
*)m
->private;
1083 struct drm_device
*dev
= node
->minor
->dev
;
1084 struct amdgpu_device
*adev
= dev
->dev_private
;
1085 struct dc
*dc
= adev
->dm
.dc
;
1086 unsigned int backlight
= dc_get_current_backlight_pwm(dc
);
1088 seq_printf(m
, "0x%x\n", backlight
);
1093 * Backlight value that is being approached. Read only.
1094 * As written to display, taking ABM and backlight lut into account.
1095 * Ranges from 0x0 to 0x10000 (= 100% PWM)
1097 static int target_backlight_read(struct seq_file
*m
, void *data
)
1099 struct drm_info_node
*node
= (struct drm_info_node
*)m
->private;
1100 struct drm_device
*dev
= node
->minor
->dev
;
1101 struct amdgpu_device
*adev
= dev
->dev_private
;
1102 struct dc
*dc
= adev
->dm
.dc
;
1103 unsigned int backlight
= dc_get_target_backlight_pwm(dc
);
1105 seq_printf(m
, "0x%x\n", backlight
);
1109 static int mst_topo(struct seq_file
*m
, void *unused
)
1111 struct drm_info_node
*node
= (struct drm_info_node
*)m
->private;
1112 struct drm_device
*dev
= node
->minor
->dev
;
1113 struct drm_connector
*connector
;
1114 struct drm_connector_list_iter conn_iter
;
1115 struct amdgpu_dm_connector
*aconnector
;
1117 drm_connector_list_iter_begin(dev
, &conn_iter
);
1118 drm_for_each_connector_iter(connector
, &conn_iter
) {
1119 if (connector
->connector_type
!= DRM_MODE_CONNECTOR_DisplayPort
)
1122 aconnector
= to_amdgpu_dm_connector(connector
);
1124 seq_printf(m
, "\nMST topology for connector %d\n", aconnector
->connector_id
);
1125 drm_dp_mst_dump_topology(m
, &aconnector
->mst_mgr
);
1127 drm_connector_list_iter_end(&conn_iter
);
1132 static const struct drm_info_list amdgpu_dm_debugfs_list
[] = {
1133 {"amdgpu_current_backlight_pwm", ¤t_backlight_read
},
1134 {"amdgpu_target_backlight_pwm", &target_backlight_read
},
1135 {"amdgpu_mst_topology", &mst_topo
},
1139 * Sets the DC visual confirm debug option from the given string.
1140 * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_visual_confirm
1142 static int visual_confirm_set(void *data
, u64 val
)
1144 struct amdgpu_device
*adev
= data
;
1146 adev
->dm
.dc
->debug
.visual_confirm
= (enum visual_confirm
)val
;
1152 * Reads the DC visual confirm debug option value into the given buffer.
1153 * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_visual_confirm
1155 static int visual_confirm_get(void *data
, u64
*val
)
1157 struct amdgpu_device
*adev
= data
;
1159 *val
= adev
->dm
.dc
->debug
.visual_confirm
;
1164 DEFINE_DEBUGFS_ATTRIBUTE(visual_confirm_fops
, visual_confirm_get
,
1165 visual_confirm_set
, "%llu\n");
1167 int dtn_debugfs_init(struct amdgpu_device
*adev
)
1169 static const struct file_operations dtn_log_fops
= {
1170 .owner
= THIS_MODULE
,
1171 .read
= dtn_log_read
,
1172 .write
= dtn_log_write
,
1173 .llseek
= default_llseek
1176 struct drm_minor
*minor
= adev
->ddev
->primary
;
1177 struct dentry
*root
= minor
->debugfs_root
;
1180 ret
= amdgpu_debugfs_add_files(adev
, amdgpu_dm_debugfs_list
,
1181 ARRAY_SIZE(amdgpu_dm_debugfs_list
));
1185 debugfs_create_file("amdgpu_dm_dtn_log", 0644, root
, adev
,
1188 debugfs_create_file_unsafe("amdgpu_dm_visual_confirm", 0644, root
, adev
,
1189 &visual_confirm_fops
);