From: Thierry Reding <tred...@nvidia.com>

The new drm_dp_dpcd_dump() helper dumps the contents of a DPCD to a
seq_file and can be used to make the DPCD available via debugfs for
example.

Signed-off-by: Thierry Reding <treding at nvidia.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 146 ++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_dp_helper.h     |   2 +
 2 files changed, 148 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 8968201ea93c..ea74884c9cb3 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -27,6 +27,7 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/i2c.h>
+#include <linux/seq_file.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drmP.h>

@@ -292,6 +293,151 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
 }
 EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);

+/**
+ * drm_dp_dpcd_dump() - dump DPCD content
+ * @aux: DisplayPort AUX channel
+ * @s: destination for DPCD dump
+ *
+ * Reads registers from the DPCD via a DisplayPort AUX channel and dumps them
+ * to a seq_file.
+ */
+void drm_dp_dpcd_dump(struct drm_dp_aux *aux, struct seq_file *s)
+{
+#define DUMP_REG(aux, offset) ({                                       \
+               u8 value;                                               \
+               int err;                                                \
+               err = drm_dp_dpcd_readb(aux, offset, &value);           \
+               if (err < 0) {                                          \
+                       dev_err((aux)->dev, "failed to read %s: %d\n",  \
+                               #offset, err);                          \
+                       return;                                         \
+               }                                                       \
+               seq_printf(s, "%-35s 0x%04x 0x%02x\n", #offset, offset, \
+                          value);                                      \
+       })
+
+       DUMP_REG(aux, DP_DPCD_REV);
+       DUMP_REG(aux, DP_MAX_LINK_RATE);
+       DUMP_REG(aux, DP_MAX_LANE_COUNT);
+       DUMP_REG(aux, DP_MAX_DOWNSPREAD);
+       DUMP_REG(aux, DP_NORP);
+       DUMP_REG(aux, DP_DOWNSTREAMPORT_PRESENT);
+       DUMP_REG(aux, DP_MAIN_LINK_CHANNEL_CODING);
+       DUMP_REG(aux, DP_DOWN_STREAM_PORT_COUNT);
+       DUMP_REG(aux, DP_RECEIVE_PORT_0_CAP_0);
+       DUMP_REG(aux, DP_RECEIVE_PORT_0_BUFFER_SIZE);
+       DUMP_REG(aux, DP_RECEIVE_PORT_1_CAP_0);
+       DUMP_REG(aux, DP_RECEIVE_PORT_1_BUFFER_SIZE);
+       DUMP_REG(aux, DP_I2C_SPEED_CAP);
+       DUMP_REG(aux, DP_EDP_CONFIGURATION_CAP);
+       DUMP_REG(aux, DP_TRAINING_AUX_RD_INTERVAL);
+       DUMP_REG(aux, DP_ADAPTER_CAP);
+       DUMP_REG(aux, DP_SUPPORTED_LINK_RATES);
+       DUMP_REG(aux, DP_FAUX_CAP);
+       DUMP_REG(aux, DP_MSTM_CAP);
+       DUMP_REG(aux, DP_NUMBER_OF_AUDIO_ENDPOINTS);
+       DUMP_REG(aux, DP_AV_GRANULARITY);
+       DUMP_REG(aux, DP_AUD_DEC_LAT0);
+       DUMP_REG(aux, DP_AUD_DEC_LAT1);
+       DUMP_REG(aux, DP_AUD_PP_LAT0);
+       DUMP_REG(aux, DP_AUD_PP_LAT1);
+       DUMP_REG(aux, DP_VID_INTER_LAT);
+       DUMP_REG(aux, DP_VID_PROG_LAT);
+       DUMP_REG(aux, DP_REP_LAT);
+       DUMP_REG(aux, DP_AUD_DEL_INS0);
+       DUMP_REG(aux, DP_AUD_DEL_INS1);
+       DUMP_REG(aux, DP_AUD_DEL_INS2);
+       DUMP_REG(aux, DP_RECEIVER_ALPM_CAP);
+       DUMP_REG(aux, DP_AUD_DEL_INS0);
+       DUMP_REG(aux, DP_GUID);
+       DUMP_REG(aux, DP_PSR_SUPPORT);
+       DUMP_REG(aux, DP_PSR_CAPS);
+       DUMP_REG(aux, DP_DOWNSTREAM_PORT_0);
+       DUMP_REG(aux, DP_LINK_BW_SET);
+       DUMP_REG(aux, DP_LANE_COUNT_SET);
+       DUMP_REG(aux, DP_TRAINING_PATTERN_SET);
+       DUMP_REG(aux, DP_TRAINING_LANE0_SET);
+       DUMP_REG(aux, DP_TRAINING_LANE1_SET);
+       DUMP_REG(aux, DP_TRAINING_LANE2_SET);
+       DUMP_REG(aux, DP_TRAINING_LANE3_SET);
+       DUMP_REG(aux, DP_DOWNSPREAD_CTRL);
+       DUMP_REG(aux, DP_MAIN_LINK_CHANNEL_CODING_SET);
+       DUMP_REG(aux, DP_I2C_SPEED_CONTROL_STATUS);
+       DUMP_REG(aux, DP_EDP_CONFIGURATION_SET);
+       DUMP_REG(aux, DP_LINK_QUAL_LANE0_SET);
+       DUMP_REG(aux, DP_LINK_QUAL_LANE1_SET);
+       DUMP_REG(aux, DP_LINK_QUAL_LANE2_SET);
+       DUMP_REG(aux, DP_LINK_QUAL_LANE3_SET);
+       DUMP_REG(aux, DP_TRAINING_LANE0_1_SET2);
+       DUMP_REG(aux, DP_TRAINING_LANE2_3_SET2);
+       DUMP_REG(aux, DP_MSTM_CTRL);
+       DUMP_REG(aux, DP_AUDIO_DELAY0);
+       DUMP_REG(aux, DP_AUDIO_DELAY1);
+       DUMP_REG(aux, DP_AUDIO_DELAY2);
+       DUMP_REG(aux, DP_LINK_RATE_SET);
+       DUMP_REG(aux, DP_RECEIVER_ALPM_CONFIG);
+       DUMP_REG(aux, DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF);
+       DUMP_REG(aux, DP_UPSTREAM_DEVICE_DP_PWR_NEED);
+       DUMP_REG(aux, DP_AUX_FRAME_SYNC_VALUE);
+       DUMP_REG(aux, DP_PSR_EN_CFG);
+       DUMP_REG(aux, DP_ADAPTER_CTRL);
+       DUMP_REG(aux, DP_BRANCH_DEVICE_CTRL);
+       DUMP_REG(aux, DP_PAYLOAD_ALLOCATE_SET);
+       DUMP_REG(aux, DP_PAYLOAD_ALLOCATE_START_TIME_SLOT);
+       DUMP_REG(aux, DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT);
+       DUMP_REG(aux, DP_SINK_COUNT);
+       DUMP_REG(aux, DP_DEVICE_SERVICE_IRQ_VECTOR);
+       DUMP_REG(aux, DP_LANE0_1_STATUS);
+       DUMP_REG(aux, DP_LANE2_3_STATUS);
+       DUMP_REG(aux, DP_LANE_ALIGN_STATUS_UPDATED);
+       DUMP_REG(aux, DP_SINK_STATUS);
+       DUMP_REG(aux, DP_ADJUST_REQUEST_LANE0_1);
+       DUMP_REG(aux, DP_ADJUST_REQUEST_LANE2_3);
+       DUMP_REG(aux, DP_TEST_REQUEST);
+       DUMP_REG(aux, DP_TEST_LINK_RATE);
+       DUMP_REG(aux, DP_TEST_LANE_COUNT);
+       DUMP_REG(aux, DP_TEST_CRC_R_CR);
+       DUMP_REG(aux, DP_TEST_CRC_G_Y);
+       DUMP_REG(aux, DP_TEST_CRC_B_CB);
+       DUMP_REG(aux, DP_TEST_SINK_MISC);
+       DUMP_REG(aux, DP_TEST_RESPONSE);
+       DUMP_REG(aux, DP_TEST_EDID_CHECKSUM);
+       DUMP_REG(aux, DP_TEST_SINK);
+       DUMP_REG(aux, DP_PAYLOAD_TABLE_UPDATE_STATUS);
+       DUMP_REG(aux, DP_VC_PAYLOAD_ID_SLOT_1);
+       DUMP_REG(aux, DP_SOURCE_OUI);
+       DUMP_REG(aux, DP_SINK_OUI);
+       DUMP_REG(aux, DP_BRANCH_OUI);
+       DUMP_REG(aux, DP_SET_POWER);
+       DUMP_REG(aux, DP_EDP_DPCD_REV);
+       DUMP_REG(aux, DP_EDP_GENERAL_CAP_1);
+       DUMP_REG(aux, DP_EDP_BACKLIGHT_ADJUSTMENT_CAP);
+       DUMP_REG(aux, DP_EDP_GENERAL_CAP_2);
+       DUMP_REG(aux, DP_EDP_GENERAL_CAP_3);
+       DUMP_REG(aux, DP_EDP_DISPLAY_CONTROL_REGISTER);
+       DUMP_REG(aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER);
+       DUMP_REG(aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB);
+       DUMP_REG(aux, DP_EDP_BACKLIGHT_BRIGHTNESS_LSB);
+       DUMP_REG(aux, DP_EDP_PWMGEN_BIT_COUNT);
+       DUMP_REG(aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN);
+       DUMP_REG(aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX);
+       DUMP_REG(aux, DP_EDP_BACKLIGHT_CONTROL_STATUS);
+       DUMP_REG(aux, DP_EDP_BACKLIGHT_FREQ_SET);
+       DUMP_REG(aux, DP_EDP_BACKLIGHT_FREQ_CAP_MIN_MSB);
+       DUMP_REG(aux, DP_EDP_BACKLIGHT_FREQ_CAP_MIN_MID);
+       DUMP_REG(aux, DP_EDP_BACKLIGHT_FREQ_CAP_MIN_LSB);
+       DUMP_REG(aux, DP_EDP_BACKLIGHT_FREQ_CAP_MAX_MSB);
+       DUMP_REG(aux, DP_EDP_BACKLIGHT_FREQ_CAP_MAX_MID);
+       DUMP_REG(aux, DP_EDP_BACKLIGHT_FREQ_CAP_MAX_LSB);
+       DUMP_REG(aux, DP_EDP_DBC_MINIMUM_BRIGHTNESS_SET);
+       DUMP_REG(aux, DP_EDP_DBC_MAXIMUM_BRIGHTNESS_SET);
+       DUMP_REG(aux, DP_EDP_REGIONAL_BACKLIGHT_BASE);
+       DUMP_REG(aux, DP_EDP_REGIONAL_BACKLIGHT_0);
+
+#undef DUMP_REG
+}
+EXPORT_SYMBOL(drm_dp_dpcd_dump);
+
 static void drm_dp_link_reset(struct drm_dp_link *link)
 {
        if (!link)
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index d041bb00d6a0..089d274f857d 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -754,6 +754,8 @@ static inline ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux 
*aux,
 int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
                                 u8 status[DP_LINK_STATUS_SIZE]);

+void drm_dp_dpcd_dump(struct drm_dp_aux *aux, struct seq_file *s);
+
 /**
  * struct drm_dp_link_train_set - link training settings
  * @voltage_swing: per-lane voltage swing
-- 
2.4.5

Reply via email to