hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
....@@ -23,12 +23,117 @@
2323 *
2424 */
2525
26
-#include <linux/debugfs.h>
26
+#include <linux/uaccess.h>
27
+
28
+#include <drm/drm_debugfs.h>
2729
2830 #include "dc.h"
2931 #include "amdgpu.h"
3032 #include "amdgpu_dm.h"
3133 #include "amdgpu_dm_debugfs.h"
34
+#include "dm_helpers.h"
35
+#include "dmub/dmub_srv.h"
36
+#include "resource.h"
37
+#include "dsc.h"
38
+#include "dc_link_dp.h"
39
+
40
+struct dmub_debugfs_trace_header {
41
+ uint32_t entry_count;
42
+ uint32_t reserved[3];
43
+};
44
+
45
+struct dmub_debugfs_trace_entry {
46
+ uint32_t trace_code;
47
+ uint32_t tick_count;
48
+ uint32_t param0;
49
+ uint32_t param1;
50
+};
51
+
52
+static inline const char *yesno(bool v)
53
+{
54
+ return v ? "yes" : "no";
55
+}
56
+
57
+/* parse_write_buffer_into_params - Helper function to parse debugfs write buffer into an array
58
+ *
59
+ * Function takes in attributes passed to debugfs write entry
60
+ * and writes into param array.
61
+ * The user passes max_param_num to identify maximum number of
62
+ * parameters that could be parsed.
63
+ *
64
+ */
65
+static int parse_write_buffer_into_params(char *wr_buf, uint32_t wr_buf_size,
66
+ long *param, const char __user *buf,
67
+ int max_param_num,
68
+ uint8_t *param_nums)
69
+{
70
+ char *wr_buf_ptr = NULL;
71
+ uint32_t wr_buf_count = 0;
72
+ int r;
73
+ char *sub_str = NULL;
74
+ const char delimiter[3] = {' ', '\n', '\0'};
75
+ uint8_t param_index = 0;
76
+
77
+ *param_nums = 0;
78
+
79
+ wr_buf_ptr = wr_buf;
80
+
81
+ r = copy_from_user(wr_buf_ptr, buf, wr_buf_size);
82
+
83
+ /* r is bytes not be copied */
84
+ if (r >= wr_buf_size) {
85
+ DRM_DEBUG_DRIVER("user data not be read\n");
86
+ return -EINVAL;
87
+ }
88
+
89
+ /* check number of parameters. isspace could not differ space and \n */
90
+ while ((*wr_buf_ptr != 0xa) && (wr_buf_count < wr_buf_size)) {
91
+ /* skip space*/
92
+ while (isspace(*wr_buf_ptr) && (wr_buf_count < wr_buf_size)) {
93
+ wr_buf_ptr++;
94
+ wr_buf_count++;
95
+ }
96
+
97
+ if (wr_buf_count == wr_buf_size)
98
+ break;
99
+
100
+ /* skip non-space*/
101
+ while ((!isspace(*wr_buf_ptr)) && (wr_buf_count < wr_buf_size)) {
102
+ wr_buf_ptr++;
103
+ wr_buf_count++;
104
+ }
105
+
106
+ (*param_nums)++;
107
+
108
+ if (wr_buf_count == wr_buf_size)
109
+ break;
110
+ }
111
+
112
+ if (*param_nums > max_param_num)
113
+ *param_nums = max_param_num;
114
+
115
+ wr_buf_ptr = wr_buf; /* reset buf pointer */
116
+ wr_buf_count = 0; /* number of char already checked */
117
+
118
+ while (isspace(*wr_buf_ptr) && (wr_buf_count < wr_buf_size)) {
119
+ wr_buf_ptr++;
120
+ wr_buf_count++;
121
+ }
122
+
123
+ while (param_index < *param_nums) {
124
+ /* after strsep, wr_buf_ptr will be moved to after space */
125
+ sub_str = strsep(&wr_buf_ptr, delimiter);
126
+
127
+ r = kstrtol(sub_str, 16, &(param[param_index]));
128
+
129
+ if (r)
130
+ DRM_DEBUG_DRIVER("string to int convert error code: %d\n", r);
131
+
132
+ param_index++;
133
+ }
134
+
135
+ return 0;
136
+}
32137
33138 /* function description
34139 * get/ set DP configuration: lane_count, link_rate, spread_spectrum
....@@ -45,7 +150,7 @@
45150 *
46151 * --- to get dp configuration
47152 *
48
- * cat link_settings
153
+ * cat /sys/kernel/debug/dri/0/DP-x/link_settings
49154 *
50155 * It will list current, verified, reported, preferred dp configuration.
51156 * current -- for current video mode
....@@ -58,7 +163,7 @@
58163 * echo <lane_count> <link_rate> > link_settings
59164 *
60165 * for example, to force to 2 lane, 2.7GHz,
61
- * echo 4 0xa > link_settings
166
+ * echo 4 0xa > /sys/kernel/debug/dri/0/DP-x/link_settings
62167 *
63168 * spread_spectrum could not be changed dynamically.
64169 *
....@@ -66,7 +171,7 @@
66171 * done. please check link settings after force operation to see if HW get
67172 * programming.
68173 *
69
- * cat link_settings
174
+ * cat /sys/kernel/debug/dri/0/DP-x/link_settings
70175 *
71176 * check current and preferred settings.
72177 *
....@@ -145,60 +250,41 @@
145250 struct dc *dc = (struct dc *)link->dc;
146251 struct dc_link_settings prefer_link_settings;
147252 char *wr_buf = NULL;
148
- char *wr_buf_ptr = NULL;
149253 const uint32_t wr_buf_size = 40;
150
- int r;
151
- int bytes_from_user;
152
- char *sub_str;
153254 /* 0: lane_count; 1: link_rate */
154
- uint8_t param_index = 0;
255
+ int max_param_num = 2;
256
+ uint8_t param_nums = 0;
155257 long param[2];
156
- const char delimiter[3] = {' ', '\n', '\0'};
157
- bool valid_input = false;
258
+ bool valid_input = true;
158259
159260 if (size == 0)
160261 return -EINVAL;
161262
162263 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
163264 if (!wr_buf)
164
- return -EINVAL;
165
- wr_buf_ptr = wr_buf;
265
+ return -ENOSPC;
166266
167
- r = copy_from_user(wr_buf_ptr, buf, wr_buf_size);
168
-
169
- /* r is bytes not be copied */
170
- if (r >= wr_buf_size) {
267
+ if (parse_write_buffer_into_params(wr_buf, wr_buf_size,
268
+ (long *)param, buf,
269
+ max_param_num,
270
+ &param_nums)) {
171271 kfree(wr_buf);
172
- DRM_DEBUG_DRIVER("user data not read\n");
173272 return -EINVAL;
174273 }
175274
176
- bytes_from_user = wr_buf_size - r;
177
-
178
- while (isspace(*wr_buf_ptr))
179
- wr_buf_ptr++;
180
-
181
- while ((*wr_buf_ptr != '\0') && (param_index < 2)) {
182
-
183
- sub_str = strsep(&wr_buf_ptr, delimiter);
184
-
185
- r = kstrtol(sub_str, 16, &param[param_index]);
186
-
187
- if (r)
188
- DRM_DEBUG_DRIVER("string to int convert error code: %d\n", r);
189
-
190
- param_index++;
191
- while (isspace(*wr_buf_ptr))
192
- wr_buf_ptr++;
275
+ if (param_nums <= 0) {
276
+ kfree(wr_buf);
277
+ DRM_DEBUG_DRIVER("user data not be read\n");
278
+ return -EINVAL;
193279 }
194280
195281 switch (param[0]) {
196282 case LANE_COUNT_ONE:
197283 case LANE_COUNT_TWO:
198284 case LANE_COUNT_FOUR:
199
- valid_input = true;
200285 break;
201286 default:
287
+ valid_input = false;
202288 break;
203289 }
204290
....@@ -208,29 +294,30 @@
208294 case LINK_RATE_RBR2:
209295 case LINK_RATE_HIGH2:
210296 case LINK_RATE_HIGH3:
211
- valid_input = true;
212297 break;
213298 default:
299
+ valid_input = false;
214300 break;
215301 }
216302
217303 if (!valid_input) {
218304 kfree(wr_buf);
219305 DRM_DEBUG_DRIVER("Invalid Input value No HW will be programmed\n");
220
- return bytes_from_user;
306
+ return size;
221307 }
222308
223309 /* save user force lane_count, link_rate to preferred settings
224310 * spread spectrum will not be changed
225311 */
226312 prefer_link_settings.link_spread = link->cur_link_settings.link_spread;
313
+ prefer_link_settings.use_link_rate_set = false;
227314 prefer_link_settings.lane_count = param[0];
228315 prefer_link_settings.link_rate = param[1];
229316
230
- dc_link_set_preferred_link_settings(dc, &prefer_link_settings, link);
317
+ dc_link_set_preferred_training_settings(dc, &prefer_link_settings, NULL, link, true);
231318
232319 kfree(wr_buf);
233
- return bytes_from_user;
320
+ return size;
234321 }
235322
236323 /* function: get current DP PHY settings: voltage swing, pre-emphasis,
....@@ -321,51 +408,34 @@
321408 struct dc_link *link = connector->dc_link;
322409 struct dc *dc = (struct dc *)link->dc;
323410 char *wr_buf = NULL;
324
- char *wr_buf_ptr = NULL;
325411 uint32_t wr_buf_size = 40;
326
- int r;
327
- int bytes_from_user;
328
- char *sub_str;
329
- uint8_t param_index = 0;
330412 long param[3];
331
- const char delimiter[3] = {' ', '\n', '\0'};
332413 bool use_prefer_link_setting;
333414 struct link_training_settings link_lane_settings;
415
+ int max_param_num = 3;
416
+ uint8_t param_nums = 0;
417
+ int r = 0;
418
+
334419
335420 if (size == 0)
336
- return 0;
421
+ return -EINVAL;
337422
338423 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
339424 if (!wr_buf)
340
- return 0;
341
- wr_buf_ptr = wr_buf;
425
+ return -ENOSPC;
342426
343
- r = copy_from_user(wr_buf_ptr, buf, wr_buf_size);
344
-
345
- /* r is bytes not be copied */
346
- if (r >= wr_buf_size) {
427
+ if (parse_write_buffer_into_params(wr_buf, size,
428
+ (long *)param, buf,
429
+ max_param_num,
430
+ &param_nums)) {
347431 kfree(wr_buf);
348
- DRM_DEBUG_DRIVER("user data not be read\n");
349
- return 0;
432
+ return -EINVAL;
350433 }
351434
352
- bytes_from_user = wr_buf_size - r;
353
-
354
- while (isspace(*wr_buf_ptr))
355
- wr_buf_ptr++;
356
-
357
- while ((*wr_buf_ptr != '\0') && (param_index < 3)) {
358
-
359
- sub_str = strsep(&wr_buf_ptr, delimiter);
360
-
361
- r = kstrtol(sub_str, 16, &param[param_index]);
362
-
363
- if (r)
364
- DRM_DEBUG_DRIVER("string to int convert error code: %d\n", r);
365
-
366
- param_index++;
367
- while (isspace(*wr_buf_ptr))
368
- wr_buf_ptr++;
435
+ if (param_nums <= 0) {
436
+ kfree(wr_buf);
437
+ DRM_DEBUG_DRIVER("user data not be read\n");
438
+ return -EINVAL;
369439 }
370440
371441 if ((param[0] > VOLTAGE_SWING_MAX_LEVEL) ||
....@@ -373,7 +443,7 @@
373443 (param[2] > POST_CURSOR2_MAX_LEVEL)) {
374444 kfree(wr_buf);
375445 DRM_DEBUG_DRIVER("Invalid Input No HW will be programmed\n");
376
- return bytes_from_user;
446
+ return size;
377447 }
378448
379449 /* get link settings: lane count, link rate */
....@@ -413,7 +483,7 @@
413483 dc_link_set_drive_settings(dc, &link_lane_settings, link);
414484
415485 kfree(wr_buf);
416
- return bytes_from_user;
486
+ return size;
417487 }
418488
419489 /* function description
....@@ -480,19 +550,13 @@
480550 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
481551 struct dc_link *link = connector->dc_link;
482552 char *wr_buf = NULL;
483
- char *wr_buf_ptr = NULL;
484553 uint32_t wr_buf_size = 100;
485
- uint32_t wr_buf_count = 0;
486
- int r;
487
- int bytes_from_user;
488
- char *sub_str = NULL;
489
- uint8_t param_index = 0;
490
- uint8_t param_nums = 0;
491554 long param[11] = {0x0};
492
- const char delimiter[3] = {' ', '\n', '\0'};
555
+ int max_param_num = 11;
493556 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
494557 bool disable_hpd = false;
495558 bool valid_test_pattern = false;
559
+ uint8_t param_nums = 0;
496560 /* init with defalut 80bit custom pattern */
497561 uint8_t custom_pattern[10] = {
498562 0x1f, 0x7c, 0xf0, 0xc1, 0x07,
....@@ -506,70 +570,26 @@
506570 int i;
507571
508572 if (size == 0)
509
- return 0;
573
+ return -EINVAL;
510574
511575 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
512576 if (!wr_buf)
513
- return 0;
514
- wr_buf_ptr = wr_buf;
577
+ return -ENOSPC;
515578
516
- r = copy_from_user(wr_buf_ptr, buf, wr_buf_size);
579
+ if (parse_write_buffer_into_params(wr_buf, size,
580
+ (long *)param, buf,
581
+ max_param_num,
582
+ &param_nums)) {
583
+ kfree(wr_buf);
584
+ return -EINVAL;
585
+ }
517586
518
- /* r is bytes not be copied */
519
- if (r >= wr_buf_size) {
587
+ if (param_nums <= 0) {
520588 kfree(wr_buf);
521589 DRM_DEBUG_DRIVER("user data not be read\n");
522
- return 0;
590
+ return -EINVAL;
523591 }
524592
525
- bytes_from_user = wr_buf_size - r;
526
-
527
- /* check number of parameters. isspace could not differ space and \n */
528
- while ((*wr_buf_ptr != 0xa) && (wr_buf_count < wr_buf_size)) {
529
- /* skip space*/
530
- while (isspace(*wr_buf_ptr) && (wr_buf_count < wr_buf_size)) {
531
- wr_buf_ptr++;
532
- wr_buf_count++;
533
- }
534
-
535
- if (wr_buf_count == wr_buf_size)
536
- break;
537
-
538
- /* skip non-space*/
539
- while ((!isspace(*wr_buf_ptr)) && (wr_buf_count < wr_buf_size)) {
540
- wr_buf_ptr++;
541
- wr_buf_count++;
542
- }
543
-
544
- param_nums++;
545
-
546
- if (wr_buf_count == wr_buf_size)
547
- break;
548
- }
549
-
550
- /* max 11 parameters */
551
- if (param_nums > 11)
552
- param_nums = 11;
553
-
554
- wr_buf_ptr = wr_buf; /* reset buf pinter */
555
- wr_buf_count = 0; /* number of char already checked */
556
-
557
- while (isspace(*wr_buf_ptr) && (wr_buf_count < wr_buf_size)) {
558
- wr_buf_ptr++;
559
- wr_buf_count++;
560
- }
561
-
562
- while (param_index < param_nums) {
563
- /* after strsep, wr_buf_ptr will be moved to after space */
564
- sub_str = strsep(&wr_buf_ptr, delimiter);
565
-
566
- r = kstrtol(sub_str, 16, &param[param_index]);
567
-
568
- if (r)
569
- DRM_DEBUG_DRIVER("string to int convert error code: %d\n", r);
570
-
571
- param_index++;
572
- }
573593
574594 test_pattern = param[0];
575595
....@@ -602,7 +622,7 @@
602622 if (!valid_test_pattern) {
603623 kfree(wr_buf);
604624 DRM_DEBUG_DRIVER("Invalid Test Pattern Parameters\n");
605
- return bytes_from_user;
625
+ return size;
606626 }
607627
608628 if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) {
....@@ -654,6 +674,7 @@
654674 dc_link_set_test_pattern(
655675 link,
656676 test_pattern,
677
+ DP_TEST_PATTERN_COLOR_SPACE_RGB,
657678 &link_training_settings,
658679 custom_pattern,
659680 10);
....@@ -668,8 +689,1413 @@
668689
669690 kfree(wr_buf);
670691
671
- return bytes_from_user;
692
+ return size;
672693 }
694
+
695
+/**
696
+ * Returns the DMCUB tracebuffer contents.
697
+ * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_dmub_tracebuffer
698
+ */
699
+static int dmub_tracebuffer_show(struct seq_file *m, void *data)
700
+{
701
+ struct amdgpu_device *adev = m->private;
702
+ struct dmub_srv_fb_info *fb_info = adev->dm.dmub_fb_info;
703
+ struct dmub_debugfs_trace_entry *entries;
704
+ uint8_t *tbuf_base;
705
+ uint32_t tbuf_size, max_entries, num_entries, i;
706
+
707
+ if (!fb_info)
708
+ return 0;
709
+
710
+ tbuf_base = (uint8_t *)fb_info->fb[DMUB_WINDOW_5_TRACEBUFF].cpu_addr;
711
+ if (!tbuf_base)
712
+ return 0;
713
+
714
+ tbuf_size = fb_info->fb[DMUB_WINDOW_5_TRACEBUFF].size;
715
+ max_entries = (tbuf_size - sizeof(struct dmub_debugfs_trace_header)) /
716
+ sizeof(struct dmub_debugfs_trace_entry);
717
+
718
+ num_entries =
719
+ ((struct dmub_debugfs_trace_header *)tbuf_base)->entry_count;
720
+
721
+ num_entries = min(num_entries, max_entries);
722
+
723
+ entries = (struct dmub_debugfs_trace_entry
724
+ *)(tbuf_base +
725
+ sizeof(struct dmub_debugfs_trace_header));
726
+
727
+ for (i = 0; i < num_entries; ++i) {
728
+ struct dmub_debugfs_trace_entry *entry = &entries[i];
729
+
730
+ seq_printf(m,
731
+ "trace_code=%u tick_count=%u param0=%u param1=%u\n",
732
+ entry->trace_code, entry->tick_count, entry->param0,
733
+ entry->param1);
734
+ }
735
+
736
+ return 0;
737
+}
738
+
739
+/**
740
+ * Returns the DMCUB firmware state contents.
741
+ * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_dmub_fw_state
742
+ */
743
+static int dmub_fw_state_show(struct seq_file *m, void *data)
744
+{
745
+ struct amdgpu_device *adev = m->private;
746
+ struct dmub_srv_fb_info *fb_info = adev->dm.dmub_fb_info;
747
+ uint8_t *state_base;
748
+ uint32_t state_size;
749
+
750
+ if (!fb_info)
751
+ return 0;
752
+
753
+ state_base = (uint8_t *)fb_info->fb[DMUB_WINDOW_6_FW_STATE].cpu_addr;
754
+ if (!state_base)
755
+ return 0;
756
+
757
+ state_size = fb_info->fb[DMUB_WINDOW_6_FW_STATE].size;
758
+
759
+ return seq_write(m, state_base, state_size);
760
+}
761
+
762
+/*
763
+ * Returns the current and maximum output bpc for the connector.
764
+ * Example usage: cat /sys/kernel/debug/dri/0/DP-1/output_bpc
765
+ */
766
+static int output_bpc_show(struct seq_file *m, void *data)
767
+{
768
+ struct drm_connector *connector = m->private;
769
+ struct drm_device *dev = connector->dev;
770
+ struct drm_crtc *crtc = NULL;
771
+ struct dm_crtc_state *dm_crtc_state = NULL;
772
+ int res = -ENODEV;
773
+ unsigned int bpc;
774
+
775
+ mutex_lock(&dev->mode_config.mutex);
776
+ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
777
+
778
+ if (connector->state == NULL)
779
+ goto unlock;
780
+
781
+ crtc = connector->state->crtc;
782
+ if (crtc == NULL)
783
+ goto unlock;
784
+
785
+ drm_modeset_lock(&crtc->mutex, NULL);
786
+ if (crtc->state == NULL)
787
+ goto unlock;
788
+
789
+ dm_crtc_state = to_dm_crtc_state(crtc->state);
790
+ if (dm_crtc_state->stream == NULL)
791
+ goto unlock;
792
+
793
+ switch (dm_crtc_state->stream->timing.display_color_depth) {
794
+ case COLOR_DEPTH_666:
795
+ bpc = 6;
796
+ break;
797
+ case COLOR_DEPTH_888:
798
+ bpc = 8;
799
+ break;
800
+ case COLOR_DEPTH_101010:
801
+ bpc = 10;
802
+ break;
803
+ case COLOR_DEPTH_121212:
804
+ bpc = 12;
805
+ break;
806
+ case COLOR_DEPTH_161616:
807
+ bpc = 16;
808
+ break;
809
+ default:
810
+ goto unlock;
811
+ }
812
+
813
+ seq_printf(m, "Current: %u\n", bpc);
814
+ seq_printf(m, "Maximum: %u\n", connector->display_info.bpc);
815
+ res = 0;
816
+
817
+unlock:
818
+ if (crtc)
819
+ drm_modeset_unlock(&crtc->mutex);
820
+
821
+ drm_modeset_unlock(&dev->mode_config.connection_mutex);
822
+ mutex_unlock(&dev->mode_config.mutex);
823
+
824
+ return res;
825
+}
826
+
827
+#ifdef CONFIG_DRM_AMD_DC_HDCP
828
+/*
829
+ * Returns the HDCP capability of the Display (1.4 for now).
830
+ *
831
+ * NOTE* Not all HDMI displays report their HDCP caps even when they are capable.
832
+ * Since its rare for a display to not be HDCP 1.4 capable, we set HDMI as always capable.
833
+ *
834
+ * Example usage: cat /sys/kernel/debug/dri/0/DP-1/hdcp_sink_capability
835
+ * or cat /sys/kernel/debug/dri/0/HDMI-A-1/hdcp_sink_capability
836
+ */
837
+static int hdcp_sink_capability_show(struct seq_file *m, void *data)
838
+{
839
+ struct drm_connector *connector = m->private;
840
+ struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
841
+ bool hdcp_cap, hdcp2_cap;
842
+
843
+ if (connector->status != connector_status_connected)
844
+ return -ENODEV;
845
+
846
+ seq_printf(m, "%s:%d HDCP version: ", connector->name, connector->base.id);
847
+
848
+ hdcp_cap = dc_link_is_hdcp14(aconnector->dc_link, aconnector->dc_sink->sink_signal);
849
+ hdcp2_cap = dc_link_is_hdcp22(aconnector->dc_link, aconnector->dc_sink->sink_signal);
850
+
851
+
852
+ if (hdcp_cap)
853
+ seq_printf(m, "%s ", "HDCP1.4");
854
+ if (hdcp2_cap)
855
+ seq_printf(m, "%s ", "HDCP2.2");
856
+
857
+ if (!hdcp_cap && !hdcp2_cap)
858
+ seq_printf(m, "%s ", "None");
859
+
860
+ seq_puts(m, "\n");
861
+
862
+ return 0;
863
+}
864
+#endif
865
+/* function description
866
+ *
867
+ * generic SDP message access for testing
868
+ *
869
+ * debugfs sdp_message is located at /syskernel/debug/dri/0/DP-x
870
+ *
871
+ * SDP header
872
+ * Hb0 : Secondary-Data Packet ID
873
+ * Hb1 : Secondary-Data Packet type
874
+ * Hb2 : Secondary-Data-packet-specific header, Byte 0
875
+ * Hb3 : Secondary-Data-packet-specific header, Byte 1
876
+ *
877
+ * for using custom sdp message: input 4 bytes SDP header and 32 bytes raw data
878
+ */
879
+static ssize_t dp_sdp_message_debugfs_write(struct file *f, const char __user *buf,
880
+ size_t size, loff_t *pos)
881
+{
882
+ int r;
883
+ uint8_t data[36];
884
+ struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
885
+ struct dm_crtc_state *acrtc_state;
886
+ uint32_t write_size = 36;
887
+
888
+ if (connector->base.status != connector_status_connected)
889
+ return -ENODEV;
890
+
891
+ if (size == 0)
892
+ return 0;
893
+
894
+ acrtc_state = to_dm_crtc_state(connector->base.state->crtc->state);
895
+
896
+ r = copy_from_user(data, buf, write_size);
897
+
898
+ write_size -= r;
899
+
900
+ dc_stream_send_dp_sdp(acrtc_state->stream, data, write_size);
901
+
902
+ return write_size;
903
+}
904
+
905
+static ssize_t dp_dpcd_address_write(struct file *f, const char __user *buf,
906
+ size_t size, loff_t *pos)
907
+{
908
+ int r;
909
+ struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
910
+
911
+ if (size < sizeof(connector->debugfs_dpcd_address))
912
+ return -EINVAL;
913
+
914
+ r = copy_from_user(&connector->debugfs_dpcd_address,
915
+ buf, sizeof(connector->debugfs_dpcd_address));
916
+
917
+ return size - r;
918
+}
919
+
920
+static ssize_t dp_dpcd_size_write(struct file *f, const char __user *buf,
921
+ size_t size, loff_t *pos)
922
+{
923
+ int r;
924
+ struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
925
+
926
+ if (size < sizeof(connector->debugfs_dpcd_size))
927
+ return -EINVAL;
928
+
929
+ r = copy_from_user(&connector->debugfs_dpcd_size,
930
+ buf, sizeof(connector->debugfs_dpcd_size));
931
+
932
+ if (connector->debugfs_dpcd_size > 256)
933
+ connector->debugfs_dpcd_size = 0;
934
+
935
+ return size - r;
936
+}
937
+
938
+static ssize_t dp_dpcd_data_write(struct file *f, const char __user *buf,
939
+ size_t size, loff_t *pos)
940
+{
941
+ int r;
942
+ char *data;
943
+ struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
944
+ struct dc_link *link = connector->dc_link;
945
+ uint32_t write_size = connector->debugfs_dpcd_size;
946
+
947
+ if (!write_size || size < write_size)
948
+ return -EINVAL;
949
+
950
+ data = kzalloc(write_size, GFP_KERNEL);
951
+ if (!data)
952
+ return 0;
953
+
954
+ r = copy_from_user(data, buf, write_size);
955
+
956
+ dm_helpers_dp_write_dpcd(link->ctx, link,
957
+ connector->debugfs_dpcd_address, data, write_size - r);
958
+ kfree(data);
959
+ return write_size - r;
960
+}
961
+
962
+static ssize_t dp_dpcd_data_read(struct file *f, char __user *buf,
963
+ size_t size, loff_t *pos)
964
+{
965
+ int r;
966
+ char *data;
967
+ struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
968
+ struct dc_link *link = connector->dc_link;
969
+ uint32_t read_size = connector->debugfs_dpcd_size;
970
+
971
+ if (!read_size || size < read_size)
972
+ return 0;
973
+
974
+ data = kzalloc(read_size, GFP_KERNEL);
975
+ if (!data)
976
+ return 0;
977
+
978
+ dm_helpers_dp_read_dpcd(link->ctx, link,
979
+ connector->debugfs_dpcd_address, data, read_size);
980
+
981
+ r = copy_to_user(buf, data, read_size);
982
+
983
+ kfree(data);
984
+ return read_size - r;
985
+}
986
+
987
+/* function: Read link's DSC & FEC capabilities
988
+ *
989
+ *
990
+ * Access it with the following command (you need to specify
991
+ * connector like DP-1):
992
+ *
993
+ * cat /sys/kernel/debug/dri/0/DP-X/dp_dsc_fec_support
994
+ *
995
+ */
996
+static int dp_dsc_fec_support_show(struct seq_file *m, void *data)
997
+{
998
+ struct drm_connector *connector = m->private;
999
+ struct drm_modeset_acquire_ctx ctx;
1000
+ struct drm_device *dev = connector->dev;
1001
+ struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
1002
+ int ret = 0;
1003
+ bool try_again = false;
1004
+ bool is_fec_supported = false;
1005
+ bool is_dsc_supported = false;
1006
+ struct dpcd_caps dpcd_caps;
1007
+
1008
+ drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
1009
+ do {
1010
+ try_again = false;
1011
+ ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
1012
+ if (ret) {
1013
+ if (ret == -EDEADLK) {
1014
+ ret = drm_modeset_backoff(&ctx);
1015
+ if (!ret) {
1016
+ try_again = true;
1017
+ continue;
1018
+ }
1019
+ }
1020
+ break;
1021
+ }
1022
+ if (connector->status != connector_status_connected) {
1023
+ ret = -ENODEV;
1024
+ break;
1025
+ }
1026
+ dpcd_caps = aconnector->dc_link->dpcd_caps;
1027
+ if (aconnector->port) {
1028
+ /* aconnector sets dsc_aux during get_modes call
1029
+ * if MST connector has it means it can either
1030
+ * enable DSC on the sink device or on MST branch
1031
+ * its connected to.
1032
+ */
1033
+ if (aconnector->dsc_aux) {
1034
+ is_fec_supported = true;
1035
+ is_dsc_supported = true;
1036
+ }
1037
+ } else {
1038
+ is_fec_supported = dpcd_caps.fec_cap.raw & 0x1;
1039
+ is_dsc_supported = dpcd_caps.dsc_caps.dsc_basic_caps.raw[0] & 0x1;
1040
+ }
1041
+ } while (try_again);
1042
+
1043
+ drm_modeset_drop_locks(&ctx);
1044
+ drm_modeset_acquire_fini(&ctx);
1045
+
1046
+ seq_printf(m, "FEC_Sink_Support: %s\n", yesno(is_fec_supported));
1047
+ seq_printf(m, "DSC_Sink_Support: %s\n", yesno(is_dsc_supported));
1048
+
1049
+ return ret;
1050
+}
1051
+
1052
+/* function: Trigger virtual HPD redetection on connector
1053
+ *
1054
+ * This function will perform link rediscovery, link disable
1055
+ * and enable, and dm connector state update.
1056
+ *
1057
+ * Retrigger HPD on an existing connector by echoing 1 into
1058
+ * its respectful "trigger_hotplug" debugfs entry:
1059
+ *
1060
+ * echo 1 > /sys/kernel/debug/dri/0/DP-X/trigger_hotplug
1061
+ *
1062
+ * This function can perform HPD unplug:
1063
+ *
1064
+ * echo 0 > /sys/kernel/debug/dri/0/DP-X/trigger_hotplug
1065
+ *
1066
+ */
1067
+static ssize_t dp_trigger_hotplug(struct file *f, const char __user *buf,
1068
+ size_t size, loff_t *pos)
1069
+{
1070
+ struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
1071
+ struct drm_connector *connector = &aconnector->base;
1072
+ struct dc_link *link = NULL;
1073
+ struct drm_device *dev = connector->dev;
1074
+ enum dc_connection_type new_connection_type = dc_connection_none;
1075
+ char *wr_buf = NULL;
1076
+ uint32_t wr_buf_size = 42;
1077
+ int max_param_num = 1;
1078
+ long param[1] = {0};
1079
+ uint8_t param_nums = 0;
1080
+
1081
+ if (!aconnector || !aconnector->dc_link)
1082
+ return -EINVAL;
1083
+
1084
+ if (size == 0)
1085
+ return -EINVAL;
1086
+
1087
+ wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
1088
+
1089
+ if (!wr_buf) {
1090
+ DRM_DEBUG_DRIVER("no memory to allocate write buffer\n");
1091
+ return -ENOSPC;
1092
+ }
1093
+
1094
+ if (parse_write_buffer_into_params(wr_buf, size,
1095
+ (long *)param, buf,
1096
+ max_param_num,
1097
+ &param_nums)) {
1098
+ kfree(wr_buf);
1099
+ return -EINVAL;
1100
+ }
1101
+
1102
+ if (param_nums <= 0) {
1103
+ DRM_DEBUG_DRIVER("user data not be read\n");
1104
+ kfree(wr_buf);
1105
+ return -EINVAL;
1106
+ }
1107
+
1108
+ if (param[0] == 1) {
1109
+ mutex_lock(&aconnector->hpd_lock);
1110
+
1111
+ if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type) &&
1112
+ new_connection_type != dc_connection_none)
1113
+ goto unlock;
1114
+
1115
+ if (!dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD))
1116
+ goto unlock;
1117
+
1118
+ amdgpu_dm_update_connector_after_detect(aconnector);
1119
+
1120
+ drm_modeset_lock_all(dev);
1121
+ dm_restore_drm_connector_state(dev, connector);
1122
+ drm_modeset_unlock_all(dev);
1123
+
1124
+ drm_kms_helper_hotplug_event(dev);
1125
+ } else if (param[0] == 0) {
1126
+ if (!aconnector->dc_link)
1127
+ goto unlock;
1128
+
1129
+ link = aconnector->dc_link;
1130
+
1131
+ if (link->local_sink) {
1132
+ dc_sink_release(link->local_sink);
1133
+ link->local_sink = NULL;
1134
+ }
1135
+
1136
+ link->dpcd_sink_count = 0;
1137
+ link->type = dc_connection_none;
1138
+ link->dongle_max_pix_clk = 0;
1139
+
1140
+ amdgpu_dm_update_connector_after_detect(aconnector);
1141
+
1142
+ drm_modeset_lock_all(dev);
1143
+ dm_restore_drm_connector_state(dev, connector);
1144
+ drm_modeset_unlock_all(dev);
1145
+
1146
+ drm_kms_helper_hotplug_event(dev);
1147
+ }
1148
+
1149
+unlock:
1150
+ mutex_unlock(&aconnector->hpd_lock);
1151
+
1152
+ kfree(wr_buf);
1153
+ return size;
1154
+}
1155
+
1156
+/* function: read DSC status on the connector
1157
+ *
1158
+ * The read function: dp_dsc_clock_en_read
1159
+ * returns current status of DSC clock on the connector.
1160
+ * The return is a boolean flag: 1 or 0.
1161
+ *
1162
+ * Access it with the following command (you need to specify
1163
+ * connector like DP-1):
1164
+ *
1165
+ * cat /sys/kernel/debug/dri/0/DP-X/dsc_clock_en
1166
+ *
1167
+ * Expected output:
1168
+ * 1 - means that DSC is currently enabled
1169
+ * 0 - means that DSC is disabled
1170
+ */
1171
+static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
1172
+ size_t size, loff_t *pos)
1173
+{
1174
+ char *rd_buf = NULL;
1175
+ char *rd_buf_ptr = NULL;
1176
+ struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
1177
+ struct display_stream_compressor *dsc;
1178
+ struct dcn_dsc_state dsc_state = {0};
1179
+ const uint32_t rd_buf_size = 10;
1180
+ struct pipe_ctx *pipe_ctx;
1181
+ ssize_t result = 0;
1182
+ int i, r, str_len = 30;
1183
+
1184
+ rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
1185
+
1186
+ if (!rd_buf)
1187
+ return -ENOMEM;
1188
+
1189
+ rd_buf_ptr = rd_buf;
1190
+
1191
+ for (i = 0; i < MAX_PIPES; i++) {
1192
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
1193
+ if (pipe_ctx && pipe_ctx->stream &&
1194
+ pipe_ctx->stream->link == aconnector->dc_link)
1195
+ break;
1196
+ }
1197
+
1198
+ if (!pipe_ctx)
1199
+ return -ENXIO;
1200
+
1201
+ dsc = pipe_ctx->stream_res.dsc;
1202
+ if (dsc)
1203
+ dsc->funcs->dsc_read_state(dsc, &dsc_state);
1204
+
1205
+ snprintf(rd_buf_ptr, str_len,
1206
+ "%d\n",
1207
+ dsc_state.dsc_clock_en);
1208
+ rd_buf_ptr += str_len;
1209
+
1210
+ while (size) {
1211
+ if (*pos >= rd_buf_size)
1212
+ break;
1213
+
1214
+ r = put_user(*(rd_buf + result), buf);
1215
+ if (r)
1216
+ return r; /* r = -EFAULT */
1217
+
1218
+ buf += 1;
1219
+ size -= 1;
1220
+ *pos += 1;
1221
+ result += 1;
1222
+ }
1223
+
1224
+ kfree(rd_buf);
1225
+ return result;
1226
+}
1227
+
1228
+/* function: write force DSC on the connector
1229
+ *
1230
+ * The write function: dp_dsc_clock_en_write
1231
+ * enables to force DSC on the connector.
1232
+ * User can write to either force enable or force disable DSC
1233
+ * on the next modeset or set it to driver default
1234
+ *
1235
+ * Accepted inputs:
1236
+ * 0 - default DSC enablement policy
1237
+ * 1 - force enable DSC on the connector
1238
+ * 2 - force disable DSC on the connector (might cause fail in atomic_check)
1239
+ *
1240
+ * Writing DSC settings is done with the following command:
1241
+ * - To force enable DSC (you need to specify
1242
+ * connector like DP-1):
1243
+ *
1244
+ * echo 0x1 > /sys/kernel/debug/dri/0/DP-X/dsc_clock_en
1245
+ *
1246
+ * - To return to default state set the flag to zero and
1247
+ * let driver deal with DSC automatically
1248
+ * (you need to specify connector like DP-1):
1249
+ *
1250
+ * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_clock_en
1251
+ *
1252
+ */
1253
+static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf,
1254
+ size_t size, loff_t *pos)
1255
+{
1256
+ struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
1257
+ struct pipe_ctx *pipe_ctx;
1258
+ int i;
1259
+ char *wr_buf = NULL;
1260
+ uint32_t wr_buf_size = 42;
1261
+ int max_param_num = 1;
1262
+ long param[1] = {0};
1263
+ uint8_t param_nums = 0;
1264
+
1265
+ if (size == 0)
1266
+ return -EINVAL;
1267
+
1268
+ wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
1269
+
1270
+ if (!wr_buf) {
1271
+ DRM_DEBUG_DRIVER("no memory to allocate write buffer\n");
1272
+ return -ENOSPC;
1273
+ }
1274
+
1275
+ if (parse_write_buffer_into_params(wr_buf, size,
1276
+ (long *)param, buf,
1277
+ max_param_num,
1278
+ &param_nums)) {
1279
+ kfree(wr_buf);
1280
+ return -EINVAL;
1281
+ }
1282
+
1283
+ if (param_nums <= 0) {
1284
+ DRM_DEBUG_DRIVER("user data not be read\n");
1285
+ kfree(wr_buf);
1286
+ return -EINVAL;
1287
+ }
1288
+
1289
+ for (i = 0; i < MAX_PIPES; i++) {
1290
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
1291
+ if (pipe_ctx && pipe_ctx->stream &&
1292
+ pipe_ctx->stream->link == aconnector->dc_link)
1293
+ break;
1294
+ }
1295
+
1296
+ if (!pipe_ctx || !pipe_ctx->stream)
1297
+ goto done;
1298
+
1299
+ if (param[0] == 1)
1300
+ aconnector->dsc_settings.dsc_force_enable = DSC_CLK_FORCE_ENABLE;
1301
+ else if (param[0] == 2)
1302
+ aconnector->dsc_settings.dsc_force_enable = DSC_CLK_FORCE_DISABLE;
1303
+ else
1304
+ aconnector->dsc_settings.dsc_force_enable = DSC_CLK_FORCE_DEFAULT;
1305
+
1306
+done:
1307
+ kfree(wr_buf);
1308
+ return size;
1309
+}
1310
+
1311
+/* function: read DSC slice width parameter on the connector
1312
+ *
1313
+ * The read function: dp_dsc_slice_width_read
1314
+ * returns dsc slice width used in the current configuration
1315
+ * The return is an integer: 0 or other positive number
1316
+ *
1317
+ * Access the status with the following command:
1318
+ *
1319
+ * cat /sys/kernel/debug/dri/0/DP-X/dsc_slice_width
1320
+ *
1321
+ * 0 - means that DSC is disabled
1322
+ *
1323
+ * Any other number more than zero represents the
1324
+ * slice width currently used by DSC in pixels
1325
+ *
1326
+ */
1327
+static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,
1328
+ size_t size, loff_t *pos)
1329
+{
1330
+ char *rd_buf = NULL;
1331
+ char *rd_buf_ptr = NULL;
1332
+ struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
1333
+ struct display_stream_compressor *dsc;
1334
+ struct dcn_dsc_state dsc_state = {0};
1335
+ const uint32_t rd_buf_size = 100;
1336
+ struct pipe_ctx *pipe_ctx;
1337
+ ssize_t result = 0;
1338
+ int i, r, str_len = 30;
1339
+
1340
+ rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
1341
+
1342
+ if (!rd_buf)
1343
+ return -ENOMEM;
1344
+
1345
+ rd_buf_ptr = rd_buf;
1346
+
1347
+ for (i = 0; i < MAX_PIPES; i++) {
1348
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
1349
+ if (pipe_ctx && pipe_ctx->stream &&
1350
+ pipe_ctx->stream->link == aconnector->dc_link)
1351
+ break;
1352
+ }
1353
+
1354
+ if (!pipe_ctx)
1355
+ return -ENXIO;
1356
+
1357
+ dsc = pipe_ctx->stream_res.dsc;
1358
+ if (dsc)
1359
+ dsc->funcs->dsc_read_state(dsc, &dsc_state);
1360
+
1361
+ snprintf(rd_buf_ptr, str_len,
1362
+ "%d\n",
1363
+ dsc_state.dsc_slice_width);
1364
+ rd_buf_ptr += str_len;
1365
+
1366
+ while (size) {
1367
+ if (*pos >= rd_buf_size)
1368
+ break;
1369
+
1370
+ r = put_user(*(rd_buf + result), buf);
1371
+ if (r)
1372
+ return r; /* r = -EFAULT */
1373
+
1374
+ buf += 1;
1375
+ size -= 1;
1376
+ *pos += 1;
1377
+ result += 1;
1378
+ }
1379
+
1380
+ kfree(rd_buf);
1381
+ return result;
1382
+}
1383
+
1384
+/* function: write DSC slice width parameter
1385
+ *
1386
+ * The write function: dp_dsc_slice_width_write
1387
+ * overwrites automatically generated DSC configuration
1388
+ * of slice width.
1389
+ *
1390
+ * The user has to write the slice width divisible by the
1391
+ * picture width.
1392
+ *
1393
+ * Also the user has to write width in hexidecimal
1394
+ * rather than in decimal.
1395
+ *
1396
+ * Writing DSC settings is done with the following command:
1397
+ * - To force overwrite slice width: (example sets to 1920 pixels)
1398
+ *
1399
+ * echo 0x780 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_width
1400
+ *
1401
+ * - To stop overwriting and let driver find the optimal size,
1402
+ * set the width to zero:
1403
+ *
1404
+ * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_width
1405
+ *
1406
+ */
1407
+static ssize_t dp_dsc_slice_width_write(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 pipe_ctx *pipe_ctx;
1412
+ int i;
1413
+ char *wr_buf = NULL;
1414
+ uint32_t wr_buf_size = 42;
1415
+ int max_param_num = 1;
1416
+ long param[1] = {0};
1417
+ uint8_t param_nums = 0;
1418
+
1419
+ if (size == 0)
1420
+ return -EINVAL;
1421
+
1422
+ wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
1423
+
1424
+ if (!wr_buf) {
1425
+ DRM_DEBUG_DRIVER("no memory to allocate write buffer\n");
1426
+ return -ENOSPC;
1427
+ }
1428
+
1429
+ if (parse_write_buffer_into_params(wr_buf, size,
1430
+ (long *)param, buf,
1431
+ max_param_num,
1432
+ &param_nums)) {
1433
+ kfree(wr_buf);
1434
+ return -EINVAL;
1435
+ }
1436
+
1437
+ if (param_nums <= 0) {
1438
+ DRM_DEBUG_DRIVER("user data not be read\n");
1439
+ kfree(wr_buf);
1440
+ return -EINVAL;
1441
+ }
1442
+
1443
+ for (i = 0; i < MAX_PIPES; i++) {
1444
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
1445
+ if (pipe_ctx && pipe_ctx->stream &&
1446
+ pipe_ctx->stream->link == aconnector->dc_link)
1447
+ break;
1448
+ }
1449
+
1450
+ if (!pipe_ctx || !pipe_ctx->stream)
1451
+ goto done;
1452
+
1453
+ if (param[0] > 0)
1454
+ aconnector->dsc_settings.dsc_num_slices_h = DIV_ROUND_UP(
1455
+ pipe_ctx->stream->timing.h_addressable,
1456
+ param[0]);
1457
+ else
1458
+ aconnector->dsc_settings.dsc_num_slices_h = 0;
1459
+
1460
+done:
1461
+ kfree(wr_buf);
1462
+ return size;
1463
+}
1464
+
1465
+/* function: read DSC slice height parameter on the connector
1466
+ *
1467
+ * The read function: dp_dsc_slice_height_read
1468
+ * returns dsc slice height used in the current configuration
1469
+ * The return is an integer: 0 or other positive number
1470
+ *
1471
+ * Access the status with the following command:
1472
+ *
1473
+ * cat /sys/kernel/debug/dri/0/DP-X/dsc_slice_height
1474
+ *
1475
+ * 0 - means that DSC is disabled
1476
+ *
1477
+ * Any other number more than zero represents the
1478
+ * slice height currently used by DSC in pixels
1479
+ *
1480
+ */
1481
+static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,
1482
+ size_t size, loff_t *pos)
1483
+{
1484
+ char *rd_buf = NULL;
1485
+ char *rd_buf_ptr = NULL;
1486
+ struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
1487
+ struct display_stream_compressor *dsc;
1488
+ struct dcn_dsc_state dsc_state = {0};
1489
+ const uint32_t rd_buf_size = 100;
1490
+ struct pipe_ctx *pipe_ctx;
1491
+ ssize_t result = 0;
1492
+ int i, r, str_len = 30;
1493
+
1494
+ rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
1495
+
1496
+ if (!rd_buf)
1497
+ return -ENOMEM;
1498
+
1499
+ rd_buf_ptr = rd_buf;
1500
+
1501
+ for (i = 0; i < MAX_PIPES; i++) {
1502
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
1503
+ if (pipe_ctx && pipe_ctx->stream &&
1504
+ pipe_ctx->stream->link == aconnector->dc_link)
1505
+ break;
1506
+ }
1507
+
1508
+ if (!pipe_ctx)
1509
+ return -ENXIO;
1510
+
1511
+ dsc = pipe_ctx->stream_res.dsc;
1512
+ if (dsc)
1513
+ dsc->funcs->dsc_read_state(dsc, &dsc_state);
1514
+
1515
+ snprintf(rd_buf_ptr, str_len,
1516
+ "%d\n",
1517
+ dsc_state.dsc_slice_height);
1518
+ rd_buf_ptr += str_len;
1519
+
1520
+ while (size) {
1521
+ if (*pos >= rd_buf_size)
1522
+ break;
1523
+
1524
+ r = put_user(*(rd_buf + result), buf);
1525
+ if (r)
1526
+ return r; /* r = -EFAULT */
1527
+
1528
+ buf += 1;
1529
+ size -= 1;
1530
+ *pos += 1;
1531
+ result += 1;
1532
+ }
1533
+
1534
+ kfree(rd_buf);
1535
+ return result;
1536
+}
1537
+
1538
+/* function: write DSC slice height parameter
1539
+ *
1540
+ * The write function: dp_dsc_slice_height_write
1541
+ * overwrites automatically generated DSC configuration
1542
+ * of slice height.
1543
+ *
1544
+ * The user has to write the slice height divisible by the
1545
+ * picture height.
1546
+ *
1547
+ * Also the user has to write height in hexidecimal
1548
+ * rather than in decimal.
1549
+ *
1550
+ * Writing DSC settings is done with the following command:
1551
+ * - To force overwrite slice height (example sets to 128 pixels):
1552
+ *
1553
+ * echo 0x80 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_height
1554
+ *
1555
+ * - To stop overwriting and let driver find the optimal size,
1556
+ * set the height to zero:
1557
+ *
1558
+ * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_height
1559
+ *
1560
+ */
1561
+static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf,
1562
+ size_t size, loff_t *pos)
1563
+{
1564
+ struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
1565
+ struct pipe_ctx *pipe_ctx;
1566
+ int i;
1567
+ char *wr_buf = NULL;
1568
+ uint32_t wr_buf_size = 42;
1569
+ int max_param_num = 1;
1570
+ uint8_t param_nums = 0;
1571
+ long param[1] = {0};
1572
+
1573
+ if (size == 0)
1574
+ return -EINVAL;
1575
+
1576
+ wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
1577
+
1578
+ if (!wr_buf) {
1579
+ DRM_DEBUG_DRIVER("no memory to allocate write buffer\n");
1580
+ return -ENOSPC;
1581
+ }
1582
+
1583
+ if (parse_write_buffer_into_params(wr_buf, size,
1584
+ (long *)param, buf,
1585
+ max_param_num,
1586
+ &param_nums)) {
1587
+ kfree(wr_buf);
1588
+ return -EINVAL;
1589
+ }
1590
+
1591
+ if (param_nums <= 0) {
1592
+ DRM_DEBUG_DRIVER("user data not be read\n");
1593
+ kfree(wr_buf);
1594
+ return -EINVAL;
1595
+ }
1596
+
1597
+ for (i = 0; i < MAX_PIPES; i++) {
1598
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
1599
+ if (pipe_ctx && pipe_ctx->stream &&
1600
+ pipe_ctx->stream->link == aconnector->dc_link)
1601
+ break;
1602
+ }
1603
+
1604
+ if (!pipe_ctx || !pipe_ctx->stream)
1605
+ goto done;
1606
+
1607
+ if (param[0] > 0)
1608
+ aconnector->dsc_settings.dsc_num_slices_v = DIV_ROUND_UP(
1609
+ pipe_ctx->stream->timing.v_addressable,
1610
+ param[0]);
1611
+ else
1612
+ aconnector->dsc_settings.dsc_num_slices_v = 0;
1613
+
1614
+done:
1615
+ kfree(wr_buf);
1616
+ return size;
1617
+}
1618
+
1619
+/* function: read DSC target rate on the connector in bits per pixel
1620
+ *
1621
+ * The read function: dp_dsc_bits_per_pixel_read
1622
+ * returns target rate of compression in bits per pixel
1623
+ * The return is an integer: 0 or other positive integer
1624
+ *
1625
+ * Access it with the following command:
1626
+ *
1627
+ * cat /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel
1628
+ *
1629
+ * 0 - means that DSC is disabled
1630
+ */
1631
+static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
1632
+ size_t size, loff_t *pos)
1633
+{
1634
+ char *rd_buf = NULL;
1635
+ char *rd_buf_ptr = NULL;
1636
+ struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
1637
+ struct display_stream_compressor *dsc;
1638
+ struct dcn_dsc_state dsc_state = {0};
1639
+ const uint32_t rd_buf_size = 100;
1640
+ struct pipe_ctx *pipe_ctx;
1641
+ ssize_t result = 0;
1642
+ int i, r, str_len = 30;
1643
+
1644
+ rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
1645
+
1646
+ if (!rd_buf)
1647
+ return -ENOMEM;
1648
+
1649
+ rd_buf_ptr = rd_buf;
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 && pipe_ctx->stream &&
1654
+ pipe_ctx->stream->link == aconnector->dc_link)
1655
+ break;
1656
+ }
1657
+
1658
+ if (!pipe_ctx)
1659
+ return -ENXIO;
1660
+
1661
+ dsc = pipe_ctx->stream_res.dsc;
1662
+ if (dsc)
1663
+ dsc->funcs->dsc_read_state(dsc, &dsc_state);
1664
+
1665
+ snprintf(rd_buf_ptr, str_len,
1666
+ "%d\n",
1667
+ dsc_state.dsc_bits_per_pixel);
1668
+ rd_buf_ptr += str_len;
1669
+
1670
+ while (size) {
1671
+ if (*pos >= rd_buf_size)
1672
+ break;
1673
+
1674
+ r = put_user(*(rd_buf + result), buf);
1675
+ if (r)
1676
+ return r; /* r = -EFAULT */
1677
+
1678
+ buf += 1;
1679
+ size -= 1;
1680
+ *pos += 1;
1681
+ result += 1;
1682
+ }
1683
+
1684
+ kfree(rd_buf);
1685
+ return result;
1686
+}
1687
+
1688
+/* function: write DSC target rate in bits per pixel
1689
+ *
1690
+ * The write function: dp_dsc_bits_per_pixel_write
1691
+ * overwrites automatically generated DSC configuration
1692
+ * of DSC target bit rate.
1693
+ *
1694
+ * Also the user has to write bpp in hexidecimal
1695
+ * rather than in decimal.
1696
+ *
1697
+ * Writing DSC settings is done with the following command:
1698
+ * - To force overwrite rate (example sets to 256 bpp x 1/16):
1699
+ *
1700
+ * echo 0x100 > /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel
1701
+ *
1702
+ * - To stop overwriting and let driver find the optimal rate,
1703
+ * set the rate to zero:
1704
+ *
1705
+ * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel
1706
+ *
1707
+ */
1708
+static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *buf,
1709
+ size_t size, loff_t *pos)
1710
+{
1711
+ struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
1712
+ struct pipe_ctx *pipe_ctx;
1713
+ int i;
1714
+ char *wr_buf = NULL;
1715
+ uint32_t wr_buf_size = 42;
1716
+ int max_param_num = 1;
1717
+ uint8_t param_nums = 0;
1718
+ long param[1] = {0};
1719
+
1720
+ if (size == 0)
1721
+ return -EINVAL;
1722
+
1723
+ wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
1724
+
1725
+ if (!wr_buf) {
1726
+ DRM_DEBUG_DRIVER("no memory to allocate write buffer\n");
1727
+ return -ENOSPC;
1728
+ }
1729
+
1730
+ if (parse_write_buffer_into_params(wr_buf, size,
1731
+ (long *)param, buf,
1732
+ max_param_num,
1733
+ &param_nums)) {
1734
+ kfree(wr_buf);
1735
+ return -EINVAL;
1736
+ }
1737
+
1738
+ if (param_nums <= 0) {
1739
+ DRM_DEBUG_DRIVER("user data not be read\n");
1740
+ kfree(wr_buf);
1741
+ return -EINVAL;
1742
+ }
1743
+
1744
+ for (i = 0; i < MAX_PIPES; i++) {
1745
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
1746
+ if (pipe_ctx && pipe_ctx->stream &&
1747
+ pipe_ctx->stream->link == aconnector->dc_link)
1748
+ break;
1749
+ }
1750
+
1751
+ if (!pipe_ctx || !pipe_ctx->stream)
1752
+ goto done;
1753
+
1754
+ aconnector->dsc_settings.dsc_bits_per_pixel = param[0];
1755
+
1756
+done:
1757
+ kfree(wr_buf);
1758
+ return size;
1759
+}
1760
+
1761
+/* function: read DSC picture width parameter on the connector
1762
+ *
1763
+ * The read function: dp_dsc_pic_width_read
1764
+ * returns dsc picture width used in the current configuration
1765
+ * It is the same as h_addressable of the current
1766
+ * display's timing
1767
+ * The return is an integer: 0 or other positive integer
1768
+ * If 0 then DSC is disabled.
1769
+ *
1770
+ * Access it with the following command:
1771
+ *
1772
+ * cat /sys/kernel/debug/dri/0/DP-X/dsc_pic_width
1773
+ *
1774
+ * 0 - means that DSC is disabled
1775
+ */
1776
+static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
1777
+ size_t size, loff_t *pos)
1778
+{
1779
+ char *rd_buf = NULL;
1780
+ char *rd_buf_ptr = NULL;
1781
+ struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
1782
+ struct display_stream_compressor *dsc;
1783
+ struct dcn_dsc_state dsc_state = {0};
1784
+ const uint32_t rd_buf_size = 100;
1785
+ struct pipe_ctx *pipe_ctx;
1786
+ ssize_t result = 0;
1787
+ int i, r, str_len = 30;
1788
+
1789
+ rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
1790
+
1791
+ if (!rd_buf)
1792
+ return -ENOMEM;
1793
+
1794
+ rd_buf_ptr = rd_buf;
1795
+
1796
+ for (i = 0; i < MAX_PIPES; i++) {
1797
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
1798
+ if (pipe_ctx && pipe_ctx->stream &&
1799
+ pipe_ctx->stream->link == aconnector->dc_link)
1800
+ break;
1801
+ }
1802
+
1803
+ if (!pipe_ctx)
1804
+ return -ENXIO;
1805
+
1806
+ dsc = pipe_ctx->stream_res.dsc;
1807
+ if (dsc)
1808
+ dsc->funcs->dsc_read_state(dsc, &dsc_state);
1809
+
1810
+ snprintf(rd_buf_ptr, str_len,
1811
+ "%d\n",
1812
+ dsc_state.dsc_pic_width);
1813
+ rd_buf_ptr += str_len;
1814
+
1815
+ while (size) {
1816
+ if (*pos >= rd_buf_size)
1817
+ break;
1818
+
1819
+ r = put_user(*(rd_buf + result), buf);
1820
+ if (r)
1821
+ return r; /* r = -EFAULT */
1822
+
1823
+ buf += 1;
1824
+ size -= 1;
1825
+ *pos += 1;
1826
+ result += 1;
1827
+ }
1828
+
1829
+ kfree(rd_buf);
1830
+ return result;
1831
+}
1832
+
1833
+static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,
1834
+ size_t size, loff_t *pos)
1835
+{
1836
+ char *rd_buf = NULL;
1837
+ char *rd_buf_ptr = NULL;
1838
+ struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
1839
+ struct display_stream_compressor *dsc;
1840
+ struct dcn_dsc_state dsc_state = {0};
1841
+ const uint32_t rd_buf_size = 100;
1842
+ struct pipe_ctx *pipe_ctx;
1843
+ ssize_t result = 0;
1844
+ int i, r, str_len = 30;
1845
+
1846
+ rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
1847
+
1848
+ if (!rd_buf)
1849
+ return -ENOMEM;
1850
+
1851
+ rd_buf_ptr = rd_buf;
1852
+
1853
+ for (i = 0; i < MAX_PIPES; i++) {
1854
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
1855
+ if (pipe_ctx && pipe_ctx->stream &&
1856
+ pipe_ctx->stream->link == aconnector->dc_link)
1857
+ break;
1858
+ }
1859
+
1860
+ if (!pipe_ctx)
1861
+ return -ENXIO;
1862
+
1863
+ dsc = pipe_ctx->stream_res.dsc;
1864
+ if (dsc)
1865
+ dsc->funcs->dsc_read_state(dsc, &dsc_state);
1866
+
1867
+ snprintf(rd_buf_ptr, str_len,
1868
+ "%d\n",
1869
+ dsc_state.dsc_pic_height);
1870
+ rd_buf_ptr += str_len;
1871
+
1872
+ while (size) {
1873
+ if (*pos >= rd_buf_size)
1874
+ break;
1875
+
1876
+ r = put_user(*(rd_buf + result), buf);
1877
+ if (r)
1878
+ return r; /* r = -EFAULT */
1879
+
1880
+ buf += 1;
1881
+ size -= 1;
1882
+ *pos += 1;
1883
+ result += 1;
1884
+ }
1885
+
1886
+ kfree(rd_buf);
1887
+ return result;
1888
+}
1889
+
1890
+/* function: read DSC chunk size parameter on the connector
1891
+ *
1892
+ * The read function: dp_dsc_chunk_size_read
1893
+ * returns dsc chunk size set in the current configuration
1894
+ * The value is calculated automatically by DSC code
1895
+ * and depends on slice parameters and bpp target rate
1896
+ * The return is an integer: 0 or other positive integer
1897
+ * If 0 then DSC is disabled.
1898
+ *
1899
+ * Access it with the following command:
1900
+ *
1901
+ * cat /sys/kernel/debug/dri/0/DP-X/dsc_chunk_size
1902
+ *
1903
+ * 0 - means that DSC is disabled
1904
+ */
1905
+static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,
1906
+ size_t size, loff_t *pos)
1907
+{
1908
+ char *rd_buf = NULL;
1909
+ char *rd_buf_ptr = NULL;
1910
+ struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
1911
+ struct display_stream_compressor *dsc;
1912
+ struct dcn_dsc_state dsc_state = {0};
1913
+ const uint32_t rd_buf_size = 100;
1914
+ struct pipe_ctx *pipe_ctx;
1915
+ ssize_t result = 0;
1916
+ int i, r, str_len = 30;
1917
+
1918
+ rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
1919
+
1920
+ if (!rd_buf)
1921
+ return -ENOMEM;
1922
+
1923
+ rd_buf_ptr = rd_buf;
1924
+
1925
+ for (i = 0; i < MAX_PIPES; i++) {
1926
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
1927
+ if (pipe_ctx && pipe_ctx->stream &&
1928
+ pipe_ctx->stream->link == aconnector->dc_link)
1929
+ break;
1930
+ }
1931
+
1932
+ if (!pipe_ctx)
1933
+ return -ENXIO;
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_chunk_size);
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
+ return r; /* r = -EFAULT */
1951
+
1952
+ buf += 1;
1953
+ size -= 1;
1954
+ *pos += 1;
1955
+ result += 1;
1956
+ }
1957
+
1958
+ kfree(rd_buf);
1959
+ return result;
1960
+}
1961
+
1962
+/* function: read DSC slice bpg offset on the connector
1963
+ *
1964
+ * The read function: dp_dsc_slice_bpg_offset_read
1965
+ * returns dsc bpg slice offset set in the current configuration
1966
+ * The value is calculated automatically by DSC code
1967
+ * and depends on slice parameters and bpp target rate
1968
+ * The return is an integer: 0 or other positive integer
1969
+ * If 0 then DSC is disabled.
1970
+ *
1971
+ * Access it with the following command:
1972
+ *
1973
+ * cat /sys/kernel/debug/dri/0/DP-X/dsc_slice_bpg_offset
1974
+ *
1975
+ * 0 - means that DSC is disabled
1976
+ */
1977
+static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,
1978
+ size_t size, loff_t *pos)
1979
+{
1980
+ char *rd_buf = NULL;
1981
+ char *rd_buf_ptr = NULL;
1982
+ struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
1983
+ struct display_stream_compressor *dsc;
1984
+ struct dcn_dsc_state dsc_state = {0};
1985
+ const uint32_t rd_buf_size = 100;
1986
+ struct pipe_ctx *pipe_ctx;
1987
+ ssize_t result = 0;
1988
+ int i, r, str_len = 30;
1989
+
1990
+ rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
1991
+
1992
+ if (!rd_buf)
1993
+ return -ENOMEM;
1994
+
1995
+ rd_buf_ptr = rd_buf;
1996
+
1997
+ for (i = 0; i < MAX_PIPES; i++) {
1998
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
1999
+ if (pipe_ctx && pipe_ctx->stream &&
2000
+ pipe_ctx->stream->link == aconnector->dc_link)
2001
+ break;
2002
+ }
2003
+
2004
+ if (!pipe_ctx)
2005
+ return -ENXIO;
2006
+
2007
+ dsc = pipe_ctx->stream_res.dsc;
2008
+ if (dsc)
2009
+ dsc->funcs->dsc_read_state(dsc, &dsc_state);
2010
+
2011
+ snprintf(rd_buf_ptr, str_len,
2012
+ "%d\n",
2013
+ dsc_state.dsc_slice_bpg_offset);
2014
+ rd_buf_ptr += str_len;
2015
+
2016
+ while (size) {
2017
+ if (*pos >= rd_buf_size)
2018
+ break;
2019
+
2020
+ r = put_user(*(rd_buf + result), buf);
2021
+ if (r)
2022
+ return r; /* r = -EFAULT */
2023
+
2024
+ buf += 1;
2025
+ size -= 1;
2026
+ *pos += 1;
2027
+ result += 1;
2028
+ }
2029
+
2030
+ kfree(rd_buf);
2031
+ return result;
2032
+}
2033
+
2034
+DEFINE_SHOW_ATTRIBUTE(dp_dsc_fec_support);
2035
+DEFINE_SHOW_ATTRIBUTE(dmub_fw_state);
2036
+DEFINE_SHOW_ATTRIBUTE(dmub_tracebuffer);
2037
+DEFINE_SHOW_ATTRIBUTE(output_bpc);
2038
+#ifdef CONFIG_DRM_AMD_DC_HDCP
2039
+DEFINE_SHOW_ATTRIBUTE(hdcp_sink_capability);
2040
+#endif
2041
+
2042
+static const struct file_operations dp_dsc_clock_en_debugfs_fops = {
2043
+ .owner = THIS_MODULE,
2044
+ .read = dp_dsc_clock_en_read,
2045
+ .write = dp_dsc_clock_en_write,
2046
+ .llseek = default_llseek
2047
+};
2048
+
2049
+static const struct file_operations dp_dsc_slice_width_debugfs_fops = {
2050
+ .owner = THIS_MODULE,
2051
+ .read = dp_dsc_slice_width_read,
2052
+ .write = dp_dsc_slice_width_write,
2053
+ .llseek = default_llseek
2054
+};
2055
+
2056
+static const struct file_operations dp_dsc_slice_height_debugfs_fops = {
2057
+ .owner = THIS_MODULE,
2058
+ .read = dp_dsc_slice_height_read,
2059
+ .write = dp_dsc_slice_height_write,
2060
+ .llseek = default_llseek
2061
+};
2062
+
2063
+static const struct file_operations dp_dsc_bits_per_pixel_debugfs_fops = {
2064
+ .owner = THIS_MODULE,
2065
+ .read = dp_dsc_bits_per_pixel_read,
2066
+ .write = dp_dsc_bits_per_pixel_write,
2067
+ .llseek = default_llseek
2068
+};
2069
+
2070
+static const struct file_operations dp_dsc_pic_width_debugfs_fops = {
2071
+ .owner = THIS_MODULE,
2072
+ .read = dp_dsc_pic_width_read,
2073
+ .llseek = default_llseek
2074
+};
2075
+
2076
+static const struct file_operations dp_dsc_pic_height_debugfs_fops = {
2077
+ .owner = THIS_MODULE,
2078
+ .read = dp_dsc_pic_height_read,
2079
+ .llseek = default_llseek
2080
+};
2081
+
2082
+static const struct file_operations dp_dsc_chunk_size_debugfs_fops = {
2083
+ .owner = THIS_MODULE,
2084
+ .read = dp_dsc_chunk_size_read,
2085
+ .llseek = default_llseek
2086
+};
2087
+
2088
+static const struct file_operations dp_dsc_slice_bpg_offset_debugfs_fops = {
2089
+ .owner = THIS_MODULE,
2090
+ .read = dp_dsc_slice_bpg_offset_read,
2091
+ .llseek = default_llseek
2092
+};
2093
+
2094
+static const struct file_operations dp_trigger_hotplug_debugfs_fops = {
2095
+ .owner = THIS_MODULE,
2096
+ .write = dp_trigger_hotplug,
2097
+ .llseek = default_llseek
2098
+};
6732099
6742100 static const struct file_operations dp_link_settings_debugfs_fops = {
6752101 .owner = THIS_MODULE,
....@@ -691,32 +2117,367 @@
6912117 .llseek = default_llseek
6922118 };
6932119
2120
+static const struct file_operations sdp_message_fops = {
2121
+ .owner = THIS_MODULE,
2122
+ .write = dp_sdp_message_debugfs_write,
2123
+ .llseek = default_llseek
2124
+};
2125
+
2126
+static const struct file_operations dp_dpcd_address_debugfs_fops = {
2127
+ .owner = THIS_MODULE,
2128
+ .write = dp_dpcd_address_write,
2129
+ .llseek = default_llseek
2130
+};
2131
+
2132
+static const struct file_operations dp_dpcd_size_debugfs_fops = {
2133
+ .owner = THIS_MODULE,
2134
+ .write = dp_dpcd_size_write,
2135
+ .llseek = default_llseek
2136
+};
2137
+
2138
+static const struct file_operations dp_dpcd_data_debugfs_fops = {
2139
+ .owner = THIS_MODULE,
2140
+ .read = dp_dpcd_data_read,
2141
+ .write = dp_dpcd_data_write,
2142
+ .llseek = default_llseek
2143
+};
2144
+
6942145 static const struct {
6952146 char *name;
6962147 const struct file_operations *fops;
6972148 } dp_debugfs_entries[] = {
6982149 {"link_settings", &dp_link_settings_debugfs_fops},
2150
+ {"trigger_hotplug", &dp_trigger_hotplug_debugfs_fops},
6992151 {"phy_settings", &dp_phy_settings_debugfs_fop},
700
- {"test_pattern", &dp_phy_test_pattern_fops}
2152
+ {"test_pattern", &dp_phy_test_pattern_fops},
2153
+#ifdef CONFIG_DRM_AMD_DC_HDCP
2154
+ {"hdcp_sink_capability", &hdcp_sink_capability_fops},
2155
+#endif
2156
+ {"sdp_message", &sdp_message_fops},
2157
+ {"aux_dpcd_address", &dp_dpcd_address_debugfs_fops},
2158
+ {"aux_dpcd_size", &dp_dpcd_size_debugfs_fops},
2159
+ {"aux_dpcd_data", &dp_dpcd_data_debugfs_fops},
2160
+ {"dsc_clock_en", &dp_dsc_clock_en_debugfs_fops},
2161
+ {"dsc_slice_width", &dp_dsc_slice_width_debugfs_fops},
2162
+ {"dsc_slice_height", &dp_dsc_slice_height_debugfs_fops},
2163
+ {"dsc_bits_per_pixel", &dp_dsc_bits_per_pixel_debugfs_fops},
2164
+ {"dsc_pic_width", &dp_dsc_pic_width_debugfs_fops},
2165
+ {"dsc_pic_height", &dp_dsc_pic_height_debugfs_fops},
2166
+ {"dsc_chunk_size", &dp_dsc_chunk_size_debugfs_fops},
2167
+ {"dsc_slice_bpg", &dp_dsc_slice_bpg_offset_debugfs_fops},
2168
+ {"dp_dsc_fec_support", &dp_dsc_fec_support_fops}
7012169 };
7022170
703
-int connector_debugfs_init(struct amdgpu_dm_connector *connector)
2171
+#ifdef CONFIG_DRM_AMD_DC_HDCP
2172
+static const struct {
2173
+ char *name;
2174
+ const struct file_operations *fops;
2175
+} hdmi_debugfs_entries[] = {
2176
+ {"hdcp_sink_capability", &hdcp_sink_capability_fops}
2177
+};
2178
+#endif
2179
+/*
2180
+ * Force YUV420 output if available from the given mode
2181
+ */
2182
+static int force_yuv420_output_set(void *data, u64 val)
7042183 {
705
- int i;
706
- struct dentry *ent, *dir = connector->base.debugfs_entry;
2184
+ struct amdgpu_dm_connector *connector = data;
7072185
708
- if (connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
709
- for (i = 0; i < ARRAY_SIZE(dp_debugfs_entries); i++) {
710
- ent = debugfs_create_file(dp_debugfs_entries[i].name,
711
- 0644,
712
- dir,
713
- connector,
714
- dp_debugfs_entries[i].fops);
715
- if (IS_ERR(ent))
716
- return PTR_ERR(ent);
717
- }
718
- }
2186
+ connector->force_yuv420_output = (bool)val;
7192187
7202188 return 0;
7212189 }
7222190
2191
+/*
2192
+ * Check if YUV420 is forced when available from the given mode
2193
+ */
2194
+static int force_yuv420_output_get(void *data, u64 *val)
2195
+{
2196
+ struct amdgpu_dm_connector *connector = data;
2197
+
2198
+ *val = connector->force_yuv420_output;
2199
+
2200
+ return 0;
2201
+}
2202
+
2203
+DEFINE_DEBUGFS_ATTRIBUTE(force_yuv420_output_fops, force_yuv420_output_get,
2204
+ force_yuv420_output_set, "%llu\n");
2205
+
2206
+/*
2207
+ * Read PSR state
2208
+ */
2209
+static int psr_get(void *data, u64 *val)
2210
+{
2211
+ struct amdgpu_dm_connector *connector = data;
2212
+ struct dc_link *link = connector->dc_link;
2213
+ uint32_t psr_state = 0;
2214
+
2215
+ dc_link_get_psr_state(link, &psr_state);
2216
+
2217
+ *val = psr_state;
2218
+
2219
+ return 0;
2220
+}
2221
+
2222
+
2223
+DEFINE_DEBUGFS_ATTRIBUTE(psr_fops, psr_get, NULL, "%llu\n");
2224
+
2225
+void connector_debugfs_init(struct amdgpu_dm_connector *connector)
2226
+{
2227
+ int i;
2228
+ struct dentry *dir = connector->base.debugfs_entry;
2229
+
2230
+ if (connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
2231
+ connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) {
2232
+ for (i = 0; i < ARRAY_SIZE(dp_debugfs_entries); i++) {
2233
+ debugfs_create_file(dp_debugfs_entries[i].name,
2234
+ 0644, dir, connector,
2235
+ dp_debugfs_entries[i].fops);
2236
+ }
2237
+ }
2238
+ if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)
2239
+ debugfs_create_file_unsafe("psr_state", 0444, dir, connector, &psr_fops);
2240
+
2241
+ debugfs_create_file_unsafe("force_yuv420_output", 0644, dir, connector,
2242
+ &force_yuv420_output_fops);
2243
+
2244
+ debugfs_create_file("output_bpc", 0644, dir, connector,
2245
+ &output_bpc_fops);
2246
+
2247
+ connector->debugfs_dpcd_address = 0;
2248
+ connector->debugfs_dpcd_size = 0;
2249
+
2250
+#ifdef CONFIG_DRM_AMD_DC_HDCP
2251
+ if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA) {
2252
+ for (i = 0; i < ARRAY_SIZE(hdmi_debugfs_entries); i++) {
2253
+ debugfs_create_file(hdmi_debugfs_entries[i].name,
2254
+ 0644, dir, connector,
2255
+ hdmi_debugfs_entries[i].fops);
2256
+ }
2257
+ }
2258
+#endif
2259
+}
2260
+
2261
+/*
2262
+ * Writes DTN log state to the user supplied buffer.
2263
+ * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_dtn_log
2264
+ */
2265
+static ssize_t dtn_log_read(
2266
+ struct file *f,
2267
+ char __user *buf,
2268
+ size_t size,
2269
+ loff_t *pos)
2270
+{
2271
+ struct amdgpu_device *adev = file_inode(f)->i_private;
2272
+ struct dc *dc = adev->dm.dc;
2273
+ struct dc_log_buffer_ctx log_ctx = { 0 };
2274
+ ssize_t result = 0;
2275
+
2276
+ if (!buf || !size)
2277
+ return -EINVAL;
2278
+
2279
+ if (!dc->hwss.log_hw_state)
2280
+ return 0;
2281
+
2282
+ dc->hwss.log_hw_state(dc, &log_ctx);
2283
+
2284
+ if (*pos < log_ctx.pos) {
2285
+ size_t to_copy = log_ctx.pos - *pos;
2286
+
2287
+ to_copy = min(to_copy, size);
2288
+
2289
+ if (!copy_to_user(buf, log_ctx.buf + *pos, to_copy)) {
2290
+ *pos += to_copy;
2291
+ result = to_copy;
2292
+ }
2293
+ }
2294
+
2295
+ kfree(log_ctx.buf);
2296
+
2297
+ return result;
2298
+}
2299
+
2300
+/*
2301
+ * Writes DTN log state to dmesg when triggered via a write.
2302
+ * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dtn_log
2303
+ */
2304
+static ssize_t dtn_log_write(
2305
+ struct file *f,
2306
+ const char __user *buf,
2307
+ size_t size,
2308
+ loff_t *pos)
2309
+{
2310
+ struct amdgpu_device *adev = file_inode(f)->i_private;
2311
+ struct dc *dc = adev->dm.dc;
2312
+
2313
+ /* Write triggers log output via dmesg. */
2314
+ if (size == 0)
2315
+ return 0;
2316
+
2317
+ if (dc->hwss.log_hw_state)
2318
+ dc->hwss.log_hw_state(dc, NULL);
2319
+
2320
+ return size;
2321
+}
2322
+
2323
+/*
2324
+ * Backlight at this moment. Read only.
2325
+ * As written to display, taking ABM and backlight lut into account.
2326
+ * Ranges from 0x0 to 0x10000 (= 100% PWM)
2327
+ */
2328
+static int current_backlight_read(struct seq_file *m, void *data)
2329
+{
2330
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
2331
+ struct drm_device *dev = node->minor->dev;
2332
+ struct amdgpu_device *adev = drm_to_adev(dev);
2333
+ struct amdgpu_display_manager *dm = &adev->dm;
2334
+
2335
+ unsigned int backlight = dc_link_get_backlight_level(dm->backlight_link);
2336
+
2337
+ seq_printf(m, "0x%x\n", backlight);
2338
+ return 0;
2339
+}
2340
+
2341
+/*
2342
+ * Backlight value that is being approached. Read only.
2343
+ * As written to display, taking ABM and backlight lut into account.
2344
+ * Ranges from 0x0 to 0x10000 (= 100% PWM)
2345
+ */
2346
+static int target_backlight_read(struct seq_file *m, void *data)
2347
+{
2348
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
2349
+ struct drm_device *dev = node->minor->dev;
2350
+ struct amdgpu_device *adev = drm_to_adev(dev);
2351
+ struct amdgpu_display_manager *dm = &adev->dm;
2352
+
2353
+ unsigned int backlight = dc_link_get_target_backlight_pwm(dm->backlight_link);
2354
+
2355
+ seq_printf(m, "0x%x\n", backlight);
2356
+ return 0;
2357
+}
2358
+
2359
+static int mst_topo(struct seq_file *m, void *unused)
2360
+{
2361
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
2362
+ struct drm_device *dev = node->minor->dev;
2363
+ struct drm_connector *connector;
2364
+ struct drm_connector_list_iter conn_iter;
2365
+ struct amdgpu_dm_connector *aconnector;
2366
+
2367
+ drm_connector_list_iter_begin(dev, &conn_iter);
2368
+ drm_for_each_connector_iter(connector, &conn_iter) {
2369
+ if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
2370
+ continue;
2371
+
2372
+ aconnector = to_amdgpu_dm_connector(connector);
2373
+
2374
+ seq_printf(m, "\nMST topology for connector %d\n", aconnector->connector_id);
2375
+ drm_dp_mst_dump_topology(m, &aconnector->mst_mgr);
2376
+ }
2377
+ drm_connector_list_iter_end(&conn_iter);
2378
+
2379
+ return 0;
2380
+}
2381
+
2382
+static const struct drm_info_list amdgpu_dm_debugfs_list[] = {
2383
+ {"amdgpu_current_backlight_pwm", &current_backlight_read},
2384
+ {"amdgpu_target_backlight_pwm", &target_backlight_read},
2385
+ {"amdgpu_mst_topology", &mst_topo},
2386
+};
2387
+
2388
+/*
2389
+ * Sets the force_timing_sync debug optino from the given string.
2390
+ * All connected displays will be force synchronized immediately.
2391
+ * Usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_force_timing_sync
2392
+ */
2393
+static int force_timing_sync_set(void *data, u64 val)
2394
+{
2395
+ struct amdgpu_device *adev = data;
2396
+
2397
+ adev->dm.force_timing_sync = (bool)val;
2398
+
2399
+ amdgpu_dm_trigger_timing_sync(adev_to_drm(adev));
2400
+
2401
+ return 0;
2402
+}
2403
+
2404
+/*
2405
+ * Gets the force_timing_sync debug option value into the given buffer.
2406
+ * Usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_force_timing_sync
2407
+ */
2408
+static int force_timing_sync_get(void *data, u64 *val)
2409
+{
2410
+ struct amdgpu_device *adev = data;
2411
+
2412
+ *val = adev->dm.force_timing_sync;
2413
+
2414
+ return 0;
2415
+}
2416
+
2417
+DEFINE_DEBUGFS_ATTRIBUTE(force_timing_sync_ops, force_timing_sync_get,
2418
+ force_timing_sync_set, "%llu\n");
2419
+
2420
+/*
2421
+ * Sets the DC visual confirm debug option from the given string.
2422
+ * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_visual_confirm
2423
+ */
2424
+static int visual_confirm_set(void *data, u64 val)
2425
+{
2426
+ struct amdgpu_device *adev = data;
2427
+
2428
+ adev->dm.dc->debug.visual_confirm = (enum visual_confirm)val;
2429
+
2430
+ return 0;
2431
+}
2432
+
2433
+/*
2434
+ * Reads the DC visual confirm debug option value into the given buffer.
2435
+ * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_visual_confirm
2436
+ */
2437
+static int visual_confirm_get(void *data, u64 *val)
2438
+{
2439
+ struct amdgpu_device *adev = data;
2440
+
2441
+ *val = adev->dm.dc->debug.visual_confirm;
2442
+
2443
+ return 0;
2444
+}
2445
+
2446
+DEFINE_DEBUGFS_ATTRIBUTE(visual_confirm_fops, visual_confirm_get,
2447
+ visual_confirm_set, "%llu\n");
2448
+
2449
+int dtn_debugfs_init(struct amdgpu_device *adev)
2450
+{
2451
+ static const struct file_operations dtn_log_fops = {
2452
+ .owner = THIS_MODULE,
2453
+ .read = dtn_log_read,
2454
+ .write = dtn_log_write,
2455
+ .llseek = default_llseek
2456
+ };
2457
+
2458
+ struct drm_minor *minor = adev_to_drm(adev)->primary;
2459
+ struct dentry *root = minor->debugfs_root;
2460
+ int ret;
2461
+
2462
+ ret = amdgpu_debugfs_add_files(adev, amdgpu_dm_debugfs_list,
2463
+ ARRAY_SIZE(amdgpu_dm_debugfs_list));
2464
+ if (ret)
2465
+ return ret;
2466
+
2467
+ debugfs_create_file("amdgpu_dm_dtn_log", 0644, root, adev,
2468
+ &dtn_log_fops);
2469
+
2470
+ debugfs_create_file_unsafe("amdgpu_dm_visual_confirm", 0644, root, adev,
2471
+ &visual_confirm_fops);
2472
+
2473
+ debugfs_create_file_unsafe("amdgpu_dm_dmub_tracebuffer", 0644, root,
2474
+ adev, &dmub_tracebuffer_fops);
2475
+
2476
+ debugfs_create_file_unsafe("amdgpu_dm_dmub_fw_state", 0644, root,
2477
+ adev, &dmub_fw_state_fops);
2478
+
2479
+ debugfs_create_file_unsafe("amdgpu_dm_force_timing_sync", 0644, root,
2480
+ adev, &force_timing_sync_ops);
2481
+
2482
+ return 0;
2483
+}