| @@ -4793,3 +4793,99 @@ void i915_debugfs_cleanup(struct drm_minor *minor) · 4792 unmodified lines |
| 4793 | 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 | +} |