History

drm/i915: add i915 specific connector debugfs file for DPCD

Occasionally it would be interesting to read some of the DPCD registers for debug purposes, without having to resort to logging. Add an i915 specific i915_dpcd debugfs file for DP and eDP connectors to dump parts of the DPCD. Currently the DPCD addresses to be dumped are statically configured, and more can be added trivially. The implementation also makes it relatively easy to add other i915 and connector specific debugfs files in the future, as necessary. This is currently i915 specific just because there's no generic way to do AUX transactions given just a drm_connector. However it's all pretty straightforward to port to other drivers. v2: Add more DPCD registers to dump.

Jani Nikula committed 11 years ago

Commit aa7471d1 parent 51ce4db3 files · +99 −0Browse files

Unified · Split

3 files
  1. drivers/gpu/drm/i915/i915_debugfs.c +96 −0
  2. drivers/gpu/drm/i915/i915_drv.h +1 −0
  3. drivers/gpu/drm/i915/intel_dp.c +2 −0
drivers/gpu/drm/i915/i915_debugfs.c+96−0
@@ -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
4797struct 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
4808static 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
4821static 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
4855static int i915_dpcd_open(struct inode *inode, struct file *file)
4856{
4857 return single_open(file, i915_dpcd_show, inode->i_private);
4858}
4859
4860static 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 */
4877int 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}
drivers/gpu/drm/i915/i915_drv.h+1−0
@@ -3007,6 +3007,7 @@ int i915_verify_lists(struct drm_device *dev); · 3006 unmodified lines
3007/* i915_debugfs.c */3007/* i915_debugfs.c */
3008int i915_debugfs_init(struct drm_minor *minor);3008int i915_debugfs_init(struct drm_minor *minor);
3009void i915_debugfs_cleanup(struct drm_minor *minor);3009void i915_debugfs_cleanup(struct drm_minor *minor);
3010int i915_debugfs_connector_add(struct drm_connector *connector);
3010#ifdef CONFIG_DEBUG_FS3011#ifdef CONFIG_DEBUG_FS
3011void intel_display_crc_init(struct drm_device *dev);3012void intel_display_crc_init(struct drm_device *dev);
3012#else3013#else
drivers/gpu/drm/i915/intel_dp.c+2−0
@@ -5584,6 +5584,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, · 5583 unmodified lines
5584 I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);5584 I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
5585 }5585 }
5586 5586
5587 i915_debugfs_connector_add(connector);
5588
5587 return true;5589 return true;
5588}5590}
5589 5591

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t