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
47934793 drm_debugfs_remove_files(info_list, 1, minor);
47944794 }
47954795 }
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+}
drivers/gpu/drm/i915/i915_drv.h+1−0
@@ -3007,6 +3007,7 @@ int i915_verify_lists(struct drm_device *dev); · 3006 unmodified lines
30073007 /* i915_debugfs.c */
30083008 int i915_debugfs_init(struct drm_minor *minor);
30093009 void i915_debugfs_cleanup(struct drm_minor *minor);
3010+int i915_debugfs_connector_add(struct drm_connector *connector);
30103011 #ifdef CONFIG_DEBUG_FS
30113012 void intel_display_crc_init(struct drm_device *dev);
30123013 #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
55845584 I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
55855585 }
55865586
5587+ i915_debugfs_connector_add(connector);
5588+
55875589 return true;
55885590 }
55895591

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