| @@ -4793,3 +4793,99 @@ void i915_debugfs_cleanup(struct drm_minor *minor) · 4792 unmodified lines |
| 4793 | drm_debugfs_remove_files(info_list, 1, minor); | 4793 | drm_debugfs_remove_files(info_list, 1, minor); |
| 4794 | } | 4794 | } |
| 4795 | } | 4795 | } |
| | 4796 | |
| | 4797 | struct dpcd_block { |
| | 4798 | /* DPCD dump start address. */ |
| | 4799 | unsigned int offset; |
| | 4800 | /* DPCD dump end address, inclusive. If unset, .size will be used. */ |
| | 4801 | unsigned int end; |
| | 4802 | /* DPCD dump size. Used if .end is unset. If unset, defaults to 1. */ |
| | 4803 | size_t size; |
| | 4804 | /* Only valid for eDP. */ |
| | 4805 | bool edp; |
| | 4806 | }; |
| | 4807 | |
| | 4808 | static const struct dpcd_block i915_dpcd_debug[] = { |
| | 4809 | { .offset = DP_DPCD_REV, .size = DP_RECEIVER_CAP_SIZE }, |
| | 4810 | { .offset = DP_PSR_SUPPORT, .end = DP_PSR_CAPS }, |
| | 4811 | { .offset = DP_DOWNSTREAM_PORT_0, .size = 16 }, |
| | 4812 | { .offset = DP_LINK_BW_SET, .end = DP_EDP_CONFIGURATION_SET }, |
| | 4813 | { .offset = DP_SINK_COUNT, .end = DP_ADJUST_REQUEST_LANE2_3 }, |
| | 4814 | { .offset = DP_SET_POWER }, |
| | 4815 | { .offset = DP_EDP_DPCD_REV }, |
| | 4816 | { .offset = DP_EDP_GENERAL_CAP_1, .end = DP_EDP_GENERAL_CAP_3 }, |
| | 4817 | { .offset = DP_EDP_DISPLAY_CONTROL_REGISTER, .end = DP_EDP_BACKLIGHT_FREQ_CAP_MAX_LSB }, |
| | 4818 | { .offset = DP_EDP_DBC_MINIMUM_BRIGHTNESS_SET, .end = DP_EDP_DBC_MAXIMUM_BRIGHTNESS_SET }, |
| | 4819 | }; |
| | 4820 | |
| | 4821 | static int i915_dpcd_show(struct seq_file *m, void *data) |
| | 4822 | { |
| | 4823 | struct drm_connector *connector = m->private; |
| | 4824 | struct intel_dp *intel_dp = |
| | 4825 | enc_to_intel_dp(&intel_attached_encoder(connector)->base); |
| | 4826 | uint8_t buf[16]; |
| | 4827 | ssize_t err; |
| | 4828 | int i; |
| | 4829 | |
| | 4830 | for (i = 0; i < ARRAY_SIZE(i915_dpcd_debug); i++) { |
| | 4831 | const struct dpcd_block *b = &i915_dpcd_debug[i]; |
| | 4832 | size_t size = b->end ? b->end - b->offset + 1 : (b->size ?: 1); |
| | 4833 | |
| | 4834 | if (b->edp && |
| | 4835 | connector->connector_type != DRM_MODE_CONNECTOR_eDP) |
| | 4836 | continue; |
| | 4837 | |
| | 4838 | /* low tech for now */ |
| | 4839 | if (WARN_ON(size > sizeof(buf))) |
| | 4840 | continue; |
| | 4841 | |
| | 4842 | err = drm_dp_dpcd_read(&intel_dp->aux, b->offset, buf, size); |
| | 4843 | if (err <= 0) { |
| | 4844 | DRM_ERROR("dpcd read (%zu bytes at %u) failed (%zd)\n", |
| | 4845 | size, b->offset, err); |
| | 4846 | continue; |
| | 4847 | } |
| | 4848 | |
| | 4849 | seq_printf(m, "%04x: %*ph\n", b->offset, (int) size, buf); |
| | 4850 | }; |
| | 4851 | |
| | 4852 | return 0; |
| | 4853 | } |
| | 4854 | |
| | 4855 | static int i915_dpcd_open(struct inode *inode, struct file *file) |
| | 4856 | { |
| | 4857 | return single_open(file, i915_dpcd_show, inode->i_private); |
| | 4858 | } |
| | 4859 | |
| | 4860 | static const struct file_operations i915_dpcd_fops = { |
| | 4861 | .owner = THIS_MODULE, |
| | 4862 | .open = i915_dpcd_open, |
| | 4863 | .read = seq_read, |
| | 4864 | .llseek = seq_lseek, |
| | 4865 | .release = single_release, |
| | 4866 | }; |
| | 4867 | |
| | 4868 | /** |
| | 4869 | * i915_debugfs_connector_add - add i915 specific connector debugfs files |
| | 4870 | * @connector: pointer to a registered drm_connector |
| | 4871 | * |
| | 4872 | * Cleanup will be done by drm_connector_unregister() through a call to |
| | 4873 | * drm_debugfs_connector_remove(). |
| | 4874 | * |
| | 4875 | * Returns 0 on success, negative error codes on error. |
| | 4876 | */ |
| | 4877 | int i915_debugfs_connector_add(struct drm_connector *connector) |
| | 4878 | { |
| | 4879 | struct dentry *root = connector->debugfs_entry; |
| | 4880 | |
| | 4881 | /* The connector must have been registered beforehands. */ |
| | 4882 | if (!root) |
| | 4883 | return -ENODEV; |
| | 4884 | |
| | 4885 | if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort || |
| | 4886 | connector->connector_type == DRM_MODE_CONNECTOR_eDP) |
| | 4887 | debugfs_create_file("i915_dpcd", S_IRUGO, root, connector, |
| | 4888 | &i915_dpcd_fops); |
| | 4889 | |
| | 4890 | return 0; |
| | 4891 | } |