1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/uaccess.h>
27
28#include <drm/drm_debugfs.h>
29
30#include "dc.h"
31#include "amdgpu.h"
32#include "amdgpu_dm.h"
33#include "amdgpu_dm_debugfs.h"
34#include "dm_helpers.h"
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77static ssize_t dp_link_settings_read(struct file *f, char __user *buf,
78 size_t size, loff_t *pos)
79{
80 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
81 struct dc_link *link = connector->dc_link;
82 char *rd_buf = NULL;
83 char *rd_buf_ptr = NULL;
84 const uint32_t rd_buf_size = 100;
85 uint32_t result = 0;
86 uint8_t str_len = 0;
87 int r;
88
89 if (*pos & 3 || size & 3)
90 return -EINVAL;
91
92 rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
93 if (!rd_buf)
94 return 0;
95
96 rd_buf_ptr = rd_buf;
97
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;
104
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;
111
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;
118
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);
124
125 while (size) {
126 if (*pos >= rd_buf_size)
127 break;
128
129 r = put_user(*(rd_buf + result), buf);
130 if (r)
131 return r;
132
133 buf += 1;
134 size -= 1;
135 *pos += 1;
136 result += 1;
137 }
138
139 kfree(rd_buf);
140 return result;
141}
142
143static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
144 size_t size, loff_t *pos)
145{
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;
150 char *wr_buf = NULL;
151 char *wr_buf_ptr = NULL;
152 const uint32_t wr_buf_size = 40;
153 int r;
154 int bytes_from_user;
155 char *sub_str;
156
157 uint8_t param_index = 0;
158 long param[2];
159 const char delimiter[3] = {' ', '\n', '\0'};
160 bool valid_input = false;
161
162 if (size == 0)
163 return -EINVAL;
164
165 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
166 if (!wr_buf)
167 return -EINVAL;
168 wr_buf_ptr = wr_buf;
169
170 r = copy_from_user(wr_buf_ptr, buf, wr_buf_size);
171
172
173 if (r >= wr_buf_size) {
174 kfree(wr_buf);
175 DRM_DEBUG_DRIVER("user data not read\n");
176 return -EINVAL;
177 }
178
179 bytes_from_user = wr_buf_size - r;
180
181 while (isspace(*wr_buf_ptr))
182 wr_buf_ptr++;
183
184 while ((*wr_buf_ptr != '\0') && (param_index < 2)) {
185
186 sub_str = strsep(&wr_buf_ptr, delimiter);
187
188 r = kstrtol(sub_str, 16, ¶m[param_index]);
189
190 if (r)
191 DRM_DEBUG_DRIVER("string to int convert error code: %d\n", r);
192
193 param_index++;
194 while (isspace(*wr_buf_ptr))
195 wr_buf_ptr++;
196 }
197
198 switch (param[0]) {
199 case LANE_COUNT_ONE:
200 case LANE_COUNT_TWO:
201 case LANE_COUNT_FOUR:
202 valid_input = true;
203 break;
204 default:
205 break;
206 }
207
208 switch (param[1]) {
209 case LINK_RATE_LOW:
210 case LINK_RATE_HIGH:
211 case LINK_RATE_RBR2:
212 case LINK_RATE_HIGH2:
213 case LINK_RATE_HIGH3:
214 valid_input = true;
215 break;
216 default:
217 break;
218 }
219
220 if (!valid_input) {
221 kfree(wr_buf);
222 DRM_DEBUG_DRIVER("Invalid Input value No HW will be programmed\n");
223 return bytes_from_user;
224 }
225
226
227
228
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];
232
233 dc_link_set_preferred_link_settings(dc, &prefer_link_settings, link);
234
235 kfree(wr_buf);
236 return bytes_from_user;
237}
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280static ssize_t dp_phy_settings_read(struct file *f, char __user *buf,
281 size_t size, loff_t *pos)
282{
283 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
284 struct dc_link *link = connector->dc_link;
285 char *rd_buf = NULL;
286 const uint32_t rd_buf_size = 20;
287 uint32_t result = 0;
288 int r;
289
290 if (*pos & 3 || size & 3)
291 return -EINVAL;
292
293 rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
294 if (!rd_buf)
295 return -EINVAL;
296
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);
301
302 while (size) {
303 if (*pos >= rd_buf_size)
304 break;
305
306 r = put_user((*(rd_buf + result)), buf);
307 if (r)
308 return r;
309
310 buf += 1;
311 size -= 1;
312 *pos += 1;
313 result += 1;
314 }
315
316 kfree(rd_buf);
317 return result;
318}
319
320static ssize_t dp_phy_settings_write(struct file *f, const char __user *buf,
321 size_t size, loff_t *pos)
322{
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;
326 char *wr_buf = NULL;
327 char *wr_buf_ptr = NULL;
328 uint32_t wr_buf_size = 40;
329 int r;
330 int bytes_from_user;
331 char *sub_str;
332 uint8_t param_index = 0;
333 long param[3];
334 const char delimiter[3] = {' ', '\n', '\0'};
335 bool use_prefer_link_setting;
336 struct link_training_settings link_lane_settings;
337
338 if (size == 0)
339 return 0;
340
341 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
342 if (!wr_buf)
343 return 0;
344 wr_buf_ptr = wr_buf;
345
346 r = copy_from_user(wr_buf_ptr, buf, wr_buf_size);
347
348
349 if (r >= wr_buf_size) {
350 kfree(wr_buf);
351 DRM_DEBUG_DRIVER("user data not be read\n");
352 return 0;
353 }
354
355 bytes_from_user = wr_buf_size - r;
356
357 while (isspace(*wr_buf_ptr))
358 wr_buf_ptr++;
359
360 while ((*wr_buf_ptr != '\0') && (param_index < 3)) {
361
362 sub_str = strsep(&wr_buf_ptr, delimiter);
363
364 r = kstrtol(sub_str, 16, ¶m[param_index]);
365
366 if (r)
367 DRM_DEBUG_DRIVER("string to int convert error code: %d\n", r);
368
369 param_index++;
370 while (isspace(*wr_buf_ptr))
371 wr_buf_ptr++;
372 }
373
374 if ((param[0] > VOLTAGE_SWING_MAX_LEVEL) ||
375 (param[1] > PRE_EMPHASIS_MAX_LEVEL) ||
376 (param[2] > POST_CURSOR2_MAX_LEVEL)) {
377 kfree(wr_buf);
378 DRM_DEBUG_DRIVER("Invalid Input No HW will be programmed\n");
379 return bytes_from_user;
380 }
381
382
383 use_prefer_link_setting =
384 ((link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN) &&
385 (link->test_pattern_enabled));
386
387 memset(&link_lane_settings, 0, sizeof(link_lane_settings));
388
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;
396 } else {
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;
403 }
404
405
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]);
413 }
414
415
416 dc_link_set_drive_settings(dc, &link_lane_settings, link);
417
418 kfree(wr_buf);
419 return bytes_from_user;
420}
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480static ssize_t dp_phy_test_pattern_debugfs_write(struct file *f, const char __user *buf,
481 size_t size, loff_t *pos)
482{
483 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
484 struct dc_link *link = connector->dc_link;
485 char *wr_buf = NULL;
486 char *wr_buf_ptr = NULL;
487 uint32_t wr_buf_size = 100;
488 uint32_t wr_buf_count = 0;
489 int r;
490 int bytes_from_user;
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
500 uint8_t custom_pattern[10] = {
501 0x1f, 0x7c, 0xf0, 0xc1, 0x07,
502 0x1f, 0x7c, 0xf0, 0xc1, 0x07
503 };
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;
509 int i;
510
511 if (size == 0)
512 return 0;
513
514 wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL);
515 if (!wr_buf)
516 return 0;
517 wr_buf_ptr = wr_buf;
518
519 r = copy_from_user(wr_buf_ptr, buf, wr_buf_size);
520
521
522 if (r >= wr_buf_size) {
523 kfree(wr_buf);
524 DRM_DEBUG_DRIVER("user data not be read\n");
525 return 0;
526 }
527
528 bytes_from_user = wr_buf_size - r;
529
530
531 while ((*wr_buf_ptr != 0xa) && (wr_buf_count < wr_buf_size)) {
532
533 while (isspace(*wr_buf_ptr) && (wr_buf_count < wr_buf_size)) {
534 wr_buf_ptr++;
535 wr_buf_count++;
536 }
537
538 if (wr_buf_count == wr_buf_size)
539 break;
540
541
542 while ((!isspace(*wr_buf_ptr)) && (wr_buf_count < wr_buf_size)) {
543 wr_buf_ptr++;
544 wr_buf_count++;
545 }
546
547 param_nums++;
548
549 if (wr_buf_count == wr_buf_size)
550 break;
551 }
552
553
554 if (param_nums > 11)
555 param_nums = 11;
556
557 wr_buf_ptr = wr_buf;
558 wr_buf_count = 0;
559
560 while (isspace(*wr_buf_ptr) && (wr_buf_count < wr_buf_size)) {
561 wr_buf_ptr++;
562 wr_buf_count++;
563 }
564
565 while (param_index < param_nums) {
566
567 sub_str = strsep(&wr_buf_ptr, delimiter);
568
569 r = kstrtol(sub_str, 16, ¶m[param_index]);
570
571 if (r)
572 DRM_DEBUG_DRIVER("string to int convert error code: %d\n", r);
573
574 param_index++;
575 }
576
577 test_pattern = param[0];
578
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;
587 break;
588
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:
595 disable_hpd = true;
596 valid_test_pattern = true;
597 break;
598
599 default:
600 valid_test_pattern = false;
601 test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
602 break;
603 }
604
605 if (!valid_test_pattern) {
606 kfree(wr_buf);
607 DRM_DEBUG_DRIVER("Invalid Test Pattern Parameters\n");
608 return bytes_from_user;
609 }
610
611 if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) {
612 for (i = 0; i < 10; i++) {
613 if ((uint8_t) param[i + 1] != 0x0)
614 break;
615 }
616
617 if (i < 10) {
618
619 for (i = 0; i < 10; i++)
620 custom_pattern[i] = (uint8_t) param[i + 1];
621 }
622 }
623
624
625
626
627
628
629
630
631
632 if (!disable_hpd)
633 dc_link_enable_hpd(link);
634
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;
638
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;
642
643 link_training_settings.link_settings = cur_link_settings;
644
645
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;
652 }
653
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;
656
657 dc_link_set_test_pattern(
658 link,
659 test_pattern,
660 &link_training_settings,
661 custom_pattern,
662 10);
663
664
665
666
667
668
669 if (valid_test_pattern && disable_hpd)
670 dc_link_disable_hpd(link);
671
672 kfree(wr_buf);
673
674 return bytes_from_user;
675}
676
677
678
679
680
681static int output_bpc_show(struct seq_file *m, void *data)
682{
683 struct drm_connector *connector = m->private;
684 struct drm_device *dev = connector->dev;
685 struct drm_crtc *crtc = NULL;
686 struct dm_crtc_state *dm_crtc_state = NULL;
687 int res = -ENODEV;
688 unsigned int bpc;
689
690 mutex_lock(&dev->mode_config.mutex);
691 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
692
693 if (connector->state == NULL)
694 goto unlock;
695
696 crtc = connector->state->crtc;
697 if (crtc == NULL)
698 goto unlock;
699
700 drm_modeset_lock(&crtc->mutex, NULL);
701 if (crtc->state == NULL)
702 goto unlock;
703
704 dm_crtc_state = to_dm_crtc_state(crtc->state);
705 if (dm_crtc_state->stream == NULL)
706 goto unlock;
707
708 switch (dm_crtc_state->stream->timing.display_color_depth) {
709 case COLOR_DEPTH_666:
710 bpc = 6;
711 break;
712 case COLOR_DEPTH_888:
713 bpc = 8;
714 break;
715 case COLOR_DEPTH_101010:
716 bpc = 10;
717 break;
718 case COLOR_DEPTH_121212:
719 bpc = 12;
720 break;
721 case COLOR_DEPTH_161616:
722 bpc = 16;
723 break;
724 default:
725 goto unlock;
726 }
727
728 seq_printf(m, "Current: %u\n", bpc);
729 seq_printf(m, "Maximum: %u\n", connector->display_info.bpc);
730 res = 0;
731
732unlock:
733 if (crtc)
734 drm_modeset_unlock(&crtc->mutex);
735
736 drm_modeset_unlock(&dev->mode_config.connection_mutex);
737 mutex_unlock(&dev->mode_config.mutex);
738
739 return res;
740}
741
742
743
744
745
746static int vrr_range_show(struct seq_file *m, void *data)
747{
748 struct drm_connector *connector = m->private;
749 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
750
751 if (connector->status != connector_status_connected)
752 return -ENODEV;
753
754 seq_printf(m, "Min: %u\n", (unsigned int)aconnector->min_vfreq);
755 seq_printf(m, "Max: %u\n", (unsigned int)aconnector->max_vfreq);
756
757 return 0;
758}
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774static ssize_t dp_sdp_message_debugfs_write(struct file *f, const char __user *buf,
775 size_t size, loff_t *pos)
776{
777 int r;
778 uint8_t data[36];
779 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
780 struct dm_crtc_state *acrtc_state;
781 uint32_t write_size = 36;
782
783 if (connector->base.status != connector_status_connected)
784 return -ENODEV;
785
786 if (size == 0)
787 return 0;
788
789 acrtc_state = to_dm_crtc_state(connector->base.state->crtc->state);
790
791 r = copy_from_user(data, buf, write_size);
792
793 write_size -= r;
794
795 dc_stream_send_dp_sdp(acrtc_state->stream, data, write_size);
796
797 return write_size;
798}
799
800static ssize_t dp_dpcd_address_write(struct file *f, const char __user *buf,
801 size_t size, loff_t *pos)
802{
803 int r;
804 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
805
806 if (size < sizeof(connector->debugfs_dpcd_address))
807 return 0;
808
809 r = copy_from_user(&connector->debugfs_dpcd_address,
810 buf, sizeof(connector->debugfs_dpcd_address));
811
812 return size - r;
813}
814
815static ssize_t dp_dpcd_size_write(struct file *f, const char __user *buf,
816 size_t size, loff_t *pos)
817{
818 int r;
819 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
820
821 if (size < sizeof(connector->debugfs_dpcd_size))
822 return 0;
823
824 r = copy_from_user(&connector->debugfs_dpcd_size,
825 buf, sizeof(connector->debugfs_dpcd_size));
826
827 if (connector->debugfs_dpcd_size > 256)
828 connector->debugfs_dpcd_size = 0;
829
830 return size - r;
831}
832
833static ssize_t dp_dpcd_data_write(struct file *f, const char __user *buf,
834 size_t size, loff_t *pos)
835{
836 int r;
837 char *data;
838 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
839 struct dc_link *link = connector->dc_link;
840 uint32_t write_size = connector->debugfs_dpcd_size;
841
842 if (size < write_size)
843 return 0;
844
845 data = kzalloc(write_size, GFP_KERNEL);
846 if (!data)
847 return 0;
848
849 r = copy_from_user(data, buf, write_size);
850
851 dm_helpers_dp_write_dpcd(link->ctx, link,
852 connector->debugfs_dpcd_address, data, write_size - r);
853 kfree(data);
854 return write_size - r;
855}
856
857static ssize_t dp_dpcd_data_read(struct file *f, char __user *buf,
858 size_t size, loff_t *pos)
859{
860 int r;
861 char *data;
862 struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
863 struct dc_link *link = connector->dc_link;
864 uint32_t read_size = connector->debugfs_dpcd_size;
865
866 if (size < read_size)
867 return 0;
868
869 data = kzalloc(read_size, GFP_KERNEL);
870 if (!data)
871 return 0;
872
873 dm_helpers_dp_read_dpcd(link->ctx, link,
874 connector->debugfs_dpcd_address, data, read_size);
875
876 r = copy_to_user(buf, data, read_size);
877
878 kfree(data);
879 return read_size - r;
880}
881
882DEFINE_SHOW_ATTRIBUTE(output_bpc);
883DEFINE_SHOW_ATTRIBUTE(vrr_range);
884
885static const struct file_operations dp_link_settings_debugfs_fops = {
886 .owner = THIS_MODULE,
887 .read = dp_link_settings_read,
888 .write = dp_link_settings_write,
889 .llseek = default_llseek
890};
891
892static const struct file_operations dp_phy_settings_debugfs_fop = {
893 .owner = THIS_MODULE,
894 .read = dp_phy_settings_read,
895 .write = dp_phy_settings_write,
896 .llseek = default_llseek
897};
898
899static const struct file_operations dp_phy_test_pattern_fops = {
900 .owner = THIS_MODULE,
901 .write = dp_phy_test_pattern_debugfs_write,
902 .llseek = default_llseek
903};
904
905static const struct file_operations sdp_message_fops = {
906 .owner = THIS_MODULE,
907 .write = dp_sdp_message_debugfs_write,
908 .llseek = default_llseek
909};
910
911static const struct file_operations dp_dpcd_address_debugfs_fops = {
912 .owner = THIS_MODULE,
913 .write = dp_dpcd_address_write,
914 .llseek = default_llseek
915};
916
917static const struct file_operations dp_dpcd_size_debugfs_fops = {
918 .owner = THIS_MODULE,
919 .write = dp_dpcd_size_write,
920 .llseek = default_llseek
921};
922
923static const struct file_operations dp_dpcd_data_debugfs_fops = {
924 .owner = THIS_MODULE,
925 .read = dp_dpcd_data_read,
926 .write = dp_dpcd_data_write,
927 .llseek = default_llseek
928};
929
930static const struct {
931 char *name;
932 const struct file_operations *fops;
933} dp_debugfs_entries[] = {
934 {"link_settings", &dp_link_settings_debugfs_fops},
935 {"phy_settings", &dp_phy_settings_debugfs_fop},
936 {"test_pattern", &dp_phy_test_pattern_fops},
937 {"output_bpc", &output_bpc_fops},
938 {"vrr_range", &vrr_range_fops},
939 {"sdp_message", &sdp_message_fops},
940 {"aux_dpcd_address", &dp_dpcd_address_debugfs_fops},
941 {"aux_dpcd_size", &dp_dpcd_size_debugfs_fops},
942 {"aux_dpcd_data", &dp_dpcd_data_debugfs_fops}
943};
944
945void connector_debugfs_init(struct amdgpu_dm_connector *connector)
946{
947 int i;
948 struct dentry *dir = connector->base.debugfs_entry;
949
950 if (connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
951 connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) {
952 for (i = 0; i < ARRAY_SIZE(dp_debugfs_entries); i++) {
953 debugfs_create_file(dp_debugfs_entries[i].name,
954 0644, dir, connector,
955 dp_debugfs_entries[i].fops);
956 }
957 }
958}
959
960
961
962
963
964static ssize_t dtn_log_read(
965 struct file *f,
966 char __user *buf,
967 size_t size,
968 loff_t *pos)
969{
970 struct amdgpu_device *adev = file_inode(f)->i_private;
971 struct dc *dc = adev->dm.dc;
972 struct dc_log_buffer_ctx log_ctx = { 0 };
973 ssize_t result = 0;
974
975 if (!buf || !size)
976 return -EINVAL;
977
978 if (!dc->hwss.log_hw_state)
979 return 0;
980
981 dc->hwss.log_hw_state(dc, &log_ctx);
982
983 if (*pos < log_ctx.pos) {
984 size_t to_copy = log_ctx.pos - *pos;
985
986 to_copy = min(to_copy, size);
987
988 if (!copy_to_user(buf, log_ctx.buf + *pos, to_copy)) {
989 *pos += to_copy;
990 result = to_copy;
991 }
992 }
993
994 kfree(log_ctx.buf);
995
996 return result;
997}
998
999
1000
1001
1002
1003static ssize_t dtn_log_write(
1004 struct file *f,
1005 const char __user *buf,
1006 size_t size,
1007 loff_t *pos)
1008{
1009 struct amdgpu_device *adev = file_inode(f)->i_private;
1010 struct dc *dc = adev->dm.dc;
1011
1012
1013 if (size == 0)
1014 return 0;
1015
1016 if (dc->hwss.log_hw_state)
1017 dc->hwss.log_hw_state(dc, NULL);
1018
1019 return size;
1020}
1021
1022
1023
1024
1025
1026
1027static int current_backlight_read(struct seq_file *m, void *data)
1028{
1029 struct drm_info_node *node = (struct drm_info_node *)m->private;
1030 struct drm_device *dev = node->minor->dev;
1031 struct amdgpu_device *adev = dev->dev_private;
1032 struct dc *dc = adev->dm.dc;
1033 unsigned int backlight = dc_get_current_backlight_pwm(dc);
1034
1035 seq_printf(m, "0x%x\n", backlight);
1036 return 0;
1037}
1038
1039
1040
1041
1042
1043
1044static int target_backlight_read(struct seq_file *m, void *data)
1045{
1046 struct drm_info_node *node = (struct drm_info_node *)m->private;
1047 struct drm_device *dev = node->minor->dev;
1048 struct amdgpu_device *adev = dev->dev_private;
1049 struct dc *dc = adev->dm.dc;
1050 unsigned int backlight = dc_get_target_backlight_pwm(dc);
1051
1052 seq_printf(m, "0x%x\n", backlight);
1053 return 0;
1054}
1055
1056static int mst_topo(struct seq_file *m, void *unused)
1057{
1058 struct drm_info_node *node = (struct drm_info_node *)m->private;
1059 struct drm_device *dev = node->minor->dev;
1060 struct drm_connector *connector;
1061 struct drm_connector_list_iter conn_iter;
1062 struct amdgpu_dm_connector *aconnector;
1063
1064 drm_connector_list_iter_begin(dev, &conn_iter);
1065 drm_for_each_connector_iter(connector, &conn_iter) {
1066 if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
1067 continue;
1068
1069 aconnector = to_amdgpu_dm_connector(connector);
1070
1071 seq_printf(m, "\nMST topology for connector %d\n", aconnector->connector_id);
1072 drm_dp_mst_dump_topology(m, &aconnector->mst_mgr);
1073 }
1074 drm_connector_list_iter_end(&conn_iter);
1075
1076 return 0;
1077}
1078
1079static const struct drm_info_list amdgpu_dm_debugfs_list[] = {
1080 {"amdgpu_current_backlight_pwm", ¤t_backlight_read},
1081 {"amdgpu_target_backlight_pwm", &target_backlight_read},
1082 {"amdgpu_mst_topology", &mst_topo},
1083};
1084
1085
1086
1087
1088
1089static int visual_confirm_set(void *data, u64 val)
1090{
1091 struct amdgpu_device *adev = data;
1092
1093 adev->dm.dc->debug.visual_confirm = (enum visual_confirm)val;
1094
1095 return 0;
1096}
1097
1098
1099
1100
1101
1102static int visual_confirm_get(void *data, u64 *val)
1103{
1104 struct amdgpu_device *adev = data;
1105
1106 *val = adev->dm.dc->debug.visual_confirm;
1107
1108 return 0;
1109}
1110
1111DEFINE_DEBUGFS_ATTRIBUTE(visual_confirm_fops, visual_confirm_get,
1112 visual_confirm_set, "%llu\n");
1113
1114int dtn_debugfs_init(struct amdgpu_device *adev)
1115{
1116 static const struct file_operations dtn_log_fops = {
1117 .owner = THIS_MODULE,
1118 .read = dtn_log_read,
1119 .write = dtn_log_write,
1120 .llseek = default_llseek
1121 };
1122
1123 struct drm_minor *minor = adev->ddev->primary;
1124 struct dentry *root = minor->debugfs_root;
1125 int ret;
1126
1127 ret = amdgpu_debugfs_add_files(adev, amdgpu_dm_debugfs_list,
1128 ARRAY_SIZE(amdgpu_dm_debugfs_list));
1129 if (ret)
1130 return ret;
1131
1132 debugfs_create_file("amdgpu_dm_dtn_log", 0644, root, adev,
1133 &dtn_log_fops);
1134
1135 debugfs_create_file_unsafe("amdgpu_dm_visual_confirm", 0644, root, adev,
1136 &visual_confirm_fops);
1137
1138 return 0;
1139}
1140