dp_debug.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  4. */
  5. #define pr_fmt(fmt)"[drm-dp] %s: " fmt, __func__
  6. #ifdef CONFIG_DEBUG_FS
  7. #include <linux/debugfs.h>
  8. #include <drm/drm_connector.h>
  9. #include <drm/drm_file.h>
  10. #include "dp_aux.h"
  11. #include "dp_ctrl.h"
  12. #include "dp_debug.h"
  13. #include "dp_display.h"
  14. #define DEBUG_NAME "msm_dp"
  15. struct msm_dp_debug_private {
  16. struct msm_dp_link *link;
  17. struct msm_dp_panel *panel;
  18. struct drm_connector *connector;
  19. };
  20. static int msm_dp_debug_show(struct seq_file *seq, void *p)
  21. {
  22. struct msm_dp_debug_private *debug = seq->private;
  23. u64 lclk = 0;
  24. u32 link_params_rate;
  25. const struct drm_display_mode *drm_mode;
  26. if (!debug)
  27. return -ENODEV;
  28. drm_mode = &debug->panel->msm_dp_mode.drm_mode;
  29. seq_printf(seq, "\tname = %s\n", DEBUG_NAME);
  30. seq_printf(seq, "\tdrm_dp_link\n\t\trate = %u\n",
  31. debug->panel->link_info.rate);
  32. seq_printf(seq, "\t\tnum_lanes = %u\n",
  33. debug->panel->link_info.num_lanes);
  34. seq_printf(seq, "\t\tcapabilities = %lu\n",
  35. debug->panel->link_info.capabilities);
  36. seq_printf(seq, "\tdp_panel_info:\n\t\tactive = %dx%d\n",
  37. drm_mode->hdisplay,
  38. drm_mode->vdisplay);
  39. seq_printf(seq, "\t\tback_porch = %dx%d\n",
  40. drm_mode->htotal - drm_mode->hsync_end,
  41. drm_mode->vtotal - drm_mode->vsync_end);
  42. seq_printf(seq, "\t\tfront_porch = %dx%d\n",
  43. drm_mode->hsync_start - drm_mode->hdisplay,
  44. drm_mode->vsync_start - drm_mode->vdisplay);
  45. seq_printf(seq, "\t\tsync_width = %dx%d\n",
  46. drm_mode->hsync_end - drm_mode->hsync_start,
  47. drm_mode->vsync_end - drm_mode->vsync_start);
  48. seq_printf(seq, "\t\tactive_low = %dx%d\n",
  49. debug->panel->msm_dp_mode.h_active_low,
  50. debug->panel->msm_dp_mode.v_active_low);
  51. seq_printf(seq, "\t\th_skew = %d\n",
  52. drm_mode->hskew);
  53. seq_printf(seq, "\t\trefresh rate = %d\n",
  54. drm_mode_vrefresh(drm_mode));
  55. seq_printf(seq, "\t\tpixel clock khz = %d\n",
  56. drm_mode->clock);
  57. seq_printf(seq, "\t\tbpp = %d\n",
  58. debug->panel->msm_dp_mode.bpp);
  59. /* Link Information */
  60. seq_printf(seq, "\tdp_link:\n\t\ttest_requested = %d\n",
  61. debug->link->sink_request);
  62. seq_printf(seq, "\t\tnum_lanes = %d\n",
  63. debug->link->link_params.num_lanes);
  64. link_params_rate = debug->link->link_params.rate;
  65. seq_printf(seq, "\t\tbw_code = %d\n",
  66. drm_dp_link_rate_to_bw_code(link_params_rate));
  67. lclk = debug->link->link_params.rate * 1000;
  68. seq_printf(seq, "\t\tlclk = %lld\n", lclk);
  69. seq_printf(seq, "\t\tv_level = %d\n",
  70. debug->link->phy_params.v_level);
  71. seq_printf(seq, "\t\tp_level = %d\n",
  72. debug->link->phy_params.p_level);
  73. return 0;
  74. }
  75. DEFINE_SHOW_ATTRIBUTE(msm_dp_debug);
  76. static int msm_dp_test_data_show(struct seq_file *m, void *data)
  77. {
  78. const struct msm_dp_debug_private *debug = m->private;
  79. const struct drm_connector *connector = debug->connector;
  80. u32 bpc;
  81. if (connector->status == connector_status_connected) {
  82. bpc = debug->link->test_video.test_bit_depth;
  83. seq_printf(m, "hdisplay: %d\n",
  84. debug->link->test_video.test_h_width);
  85. seq_printf(m, "vdisplay: %d\n",
  86. debug->link->test_video.test_v_height);
  87. seq_printf(m, "bpc: %u\n",
  88. msm_dp_link_bit_depth_to_bpp(bpc) / 3);
  89. } else {
  90. seq_puts(m, "0");
  91. }
  92. return 0;
  93. }
  94. DEFINE_SHOW_ATTRIBUTE(msm_dp_test_data);
  95. static int msm_dp_test_type_show(struct seq_file *m, void *data)
  96. {
  97. const struct msm_dp_debug_private *debug = m->private;
  98. const struct drm_connector *connector = debug->connector;
  99. if (connector->status == connector_status_connected)
  100. seq_printf(m, "%02x", DP_TEST_LINK_VIDEO_PATTERN);
  101. else
  102. seq_puts(m, "0");
  103. return 0;
  104. }
  105. DEFINE_SHOW_ATTRIBUTE(msm_dp_test_type);
  106. static ssize_t msm_dp_test_active_write(struct file *file,
  107. const char __user *ubuf,
  108. size_t len, loff_t *offp)
  109. {
  110. char *input_buffer;
  111. int status = 0;
  112. const struct msm_dp_debug_private *debug;
  113. const struct drm_connector *connector;
  114. int val = 0;
  115. debug = ((struct seq_file *)file->private_data)->private;
  116. connector = debug->connector;
  117. if (len == 0)
  118. return 0;
  119. input_buffer = memdup_user_nul(ubuf, len);
  120. if (IS_ERR(input_buffer))
  121. return PTR_ERR(input_buffer);
  122. DRM_DEBUG_DRIVER("Copied %d bytes from user\n", (unsigned int)len);
  123. if (connector->status == connector_status_connected) {
  124. status = kstrtoint(input_buffer, 10, &val);
  125. if (status < 0) {
  126. kfree(input_buffer);
  127. return status;
  128. }
  129. DRM_DEBUG_DRIVER("Got %d for test active\n", val);
  130. /* To prevent erroneous activation of the compliance
  131. * testing code, only accept an actual value of 1 here
  132. */
  133. if (val == 1)
  134. debug->panel->video_test = true;
  135. else
  136. debug->panel->video_test = false;
  137. }
  138. kfree(input_buffer);
  139. *offp += len;
  140. return len;
  141. }
  142. static int msm_dp_test_active_show(struct seq_file *m, void *data)
  143. {
  144. struct msm_dp_debug_private *debug = m->private;
  145. struct drm_connector *connector = debug->connector;
  146. if (connector->status == connector_status_connected) {
  147. if (debug->panel->video_test)
  148. seq_puts(m, "1");
  149. else
  150. seq_puts(m, "0");
  151. } else {
  152. seq_puts(m, "0");
  153. }
  154. return 0;
  155. }
  156. static int msm_dp_test_active_open(struct inode *inode,
  157. struct file *file)
  158. {
  159. return single_open(file, msm_dp_test_active_show,
  160. inode->i_private);
  161. }
  162. static const struct file_operations test_active_fops = {
  163. .owner = THIS_MODULE,
  164. .open = msm_dp_test_active_open,
  165. .read = seq_read,
  166. .llseek = seq_lseek,
  167. .release = single_release,
  168. .write = msm_dp_test_active_write
  169. };
  170. int msm_dp_debug_init(struct device *dev, struct msm_dp_panel *panel,
  171. struct msm_dp_link *link,
  172. struct drm_connector *connector,
  173. struct dentry *root, bool is_edp)
  174. {
  175. struct msm_dp_debug_private *debug;
  176. if (!dev || !panel || !link) {
  177. DRM_ERROR("invalid input\n");
  178. return -EINVAL;
  179. }
  180. debug = devm_kzalloc(dev, sizeof(*debug), GFP_KERNEL);
  181. if (!debug)
  182. return -ENOMEM;
  183. debug->link = link;
  184. debug->panel = panel;
  185. debugfs_create_file("dp_debug", 0444, root,
  186. debug, &msm_dp_debug_fops);
  187. if (!is_edp) {
  188. debugfs_create_file("dp_test_active", 0444,
  189. root,
  190. debug, &test_active_fops);
  191. debugfs_create_file("dp_test_data", 0444,
  192. root,
  193. debug, &msm_dp_test_data_fops);
  194. debugfs_create_file("dp_test_type", 0444,
  195. root,
  196. debug, &msm_dp_test_type_fops);
  197. }
  198. return 0;
  199. }
  200. #endif