[PATCH] drm/i915: debugfs: Add support for probing DP sink CRC.

Rodrigo Vivi rodrigo.vivi at gmail.com
Thu Jan 9 11:47:10 PST 2014


This debugfs interface will allow intel-gpu-tools test case
to verify if screen has been updated properly on cases like PSR.

Since the current target is PSR we will provide only the CRC check
for eDP panels. We can latter extend it to all available DP panels.
---
 drivers/gpu/drm/i915/i915_debugfs.c | 24 ++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_dp.c     | 31 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h    |  9 +++++++++
 include/drm/drm_dp_helper.h         | 10 ++++++++++
 4 files changed, 74 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 75a489e..0facff1 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1876,6 +1876,29 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 	return 0;
 }
 
+static int i915_sink_crc(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct intel_encoder *encoder;
+	struct intel_dp *intel_dp = NULL;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head)
+		if (encoder->type == INTEL_OUTPUT_EDP) {
+			intel_dp = enc_to_intel_dp(&encoder->base);
+
+			intel_dp_sink_crc(intel_dp);
+			seq_printf(m, "%02hx%02hx%02hx%02hx%02hx%02hx\n",
+				   intel_dp->sink_crc.r_cr[0],
+				   intel_dp->sink_crc.r_cr[1],
+				   intel_dp->sink_crc.g_y[0],
+				   intel_dp->sink_crc.g_y[1],
+				   intel_dp->sink_crc.b_cb[0],
+				   intel_dp->sink_crc.b_cb[1]);
+		}
+	return 0;
+}
+
 static int i915_energy_uJ(struct seq_file *m, void *data)
 {
 	struct drm_info_node *node = m->private;
@@ -3232,6 +3255,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
 	{"i915_dpio", i915_dpio_info, 0},
 	{"i915_llc", i915_llc, 0},
 	{"i915_edp_psr_status", i915_edp_psr_status, 0},
+	{"i915_sink_crc", i915_sink_crc, 0},
 	{"i915_energy_uJ", i915_energy_uJ, 0},
 	{"i915_pc8_status", i915_pc8_status, 0},
 	{"i915_power_domain_info", i915_power_domain_info, 0},
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 7df5085..9933327 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2786,6 +2786,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	char dpcd_hex_dump[sizeof(intel_dp->dpcd) * 3];
+	u8 buf[1];
 
 	if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd,
 					   sizeof(intel_dp->dpcd)) == 0)
@@ -2810,6 +2811,9 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 		}
 	}
 
+	intel_dp_aux_native_read_retry(intel_dp, DP_TEST_SINK_MISC, buf, 1);
+	intel_dp->sink_crc.supported = buf[0] & DP_TEST_CRC_SUPPORTED;
+
 	if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
 	      DP_DWN_STRM_PORT_PRESENT))
 		return true; /* native DP sink */
@@ -2846,6 +2850,33 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
 	ironlake_edp_panel_vdd_off(intel_dp, false);
 }
 
+void intel_dp_sink_crc(struct intel_dp *intel_dp)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct intel_crtc *intel_crtc =
+		to_intel_crtc(intel_dig_port->base.base.crtc);
+
+	if (!intel_dp->sink_crc.supported)
+		return;
+
+	intel_dp_aux_native_write_1(intel_dp, DP_TEST_SINK, DP_TEST_SINK_START);
+
+	/* Wait 2 vblanks to be sure we will have the correct CRC value */
+	intel_wait_for_vblank(dev, intel_crtc->pipe);
+	intel_wait_for_vblank(dev, intel_crtc->pipe);
+
+	intel_dp_aux_native_read_retry(intel_dp, DP_TEST_CRC_R_CR,
+				       intel_dp->sink_crc.r_cr, 2);
+	intel_dp_aux_native_read_retry(intel_dp, DP_TEST_CRC_G_Y,
+				       intel_dp->sink_crc.g_y, 2);
+	intel_dp_aux_native_read_retry(intel_dp, DP_TEST_CRC_B_CB,
+				       intel_dp->sink_crc.b_cb, 2);
+
+	intel_dp_aux_native_write_1(intel_dp, DP_TEST_SINK,
+				    ~DP_TEST_SINK_START);
+}
+
 static bool
 intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector)
 {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 46aea6c..48533c0 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -462,6 +462,13 @@ struct intel_hdmi {
 
 #define DP_MAX_DOWNSTREAM_PORTS		0x10
 
+struct sink_crc {
+	bool supported;
+	u8 r_cr[2];
+	u8 g_y[2];
+	u8 b_cb[2];
+};
+
 struct intel_dp {
 	uint32_t output_reg;
 	uint32_t aux_ch_ctl_reg;
@@ -487,6 +494,7 @@ struct intel_dp {
 	bool want_panel_vdd;
 	bool psr_setup_done;
 	struct intel_connector *attached_connector;
+	struct sink_crc sink_crc;
 };
 
 struct intel_digital_port {
@@ -719,6 +727,7 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp);
 void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
 void intel_dp_encoder_destroy(struct drm_encoder *encoder);
 void intel_dp_check_link_status(struct intel_dp *intel_dp);
+void intel_dp_sink_crc(struct intel_dp *intel_dp);
 bool intel_dp_compute_config(struct intel_encoder *encoder,
 			     struct intel_crtc_config *pipe_config);
 bool intel_dp_is_edp(struct drm_device *dev, enum port port);
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 1d09050..ba0b90d 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -279,11 +279,21 @@
 
 #define DP_TEST_PATTERN			    0x221
 
+#define DP_TEST_CRC_R_CR		    0x240
+#define DP_TEST_CRC_G_Y			    0x242
+#define DP_TEST_CRC_B_CB		    0x244
+
+#define DP_TEST_SINK_MISC		    0x246
+#define DP_TEST_CRC_SUPPORTED 		    (1 << 5)
+
 #define DP_TEST_RESPONSE		    0x260
 # define DP_TEST_ACK			    (1 << 0)
 # define DP_TEST_NAK			    (1 << 1)
 # define DP_TEST_EDID_CHECKSUM_WRITE	    (1 << 2)
 
+#define DP_TEST_SINK			    0x270
+#define DP_TEST_SINK_START    		    (1 << 0)
+
 #define DP_SOURCE_OUI			    0x300
 #define DP_SINK_OUI			    0x400
 #define DP_BRANCH_OUI			    0x500
-- 
1.8.3.1



More information about the dri-devel mailing list