diff mbox

[4/6] drm/i915: Update Displayport compliance test for EDID operations

Message ID 1403647974-42377-5-git-send-email-tprevite@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Todd Previte June 24, 2014, 10:12 p.m. UTC
Adds additional functionality to the EDID compliance testing operations to
further enhance Displayport compliance. Specifically this patch adds the
ability to search through the probed EDID modes and select an appropriate
mode based on the test requirements. A stub function for actually setting
the mode is included as well.

Signed-off-by: Todd Previte <tprevite@gmail.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 100 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 93 insertions(+), 7 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index d060853..4c5d229 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -82,6 +82,15 @@  static const struct dp_link_dpll chv_dpll[] = {
 		{ .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }
 };
 
+/* Enum for selecting EDID preferred or failsafe display mode
+   during DP compliance testing */
+typedef enum
+{
+	DP_COMPLIANCE_MODE_FAILSAFE = 0,
+	DP_COMPLIANCE_MODE_PREFERRED = 1
+} dp_compliance_mode;
+
+
 /**
  * is_edp - is the given port attached to an eDP panel (either CPU or PCH)
  * @intel_dp: DP struct
@@ -3332,6 +3341,65 @@  intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector)
 				       sink_irq_vector, 1) == 1;
 }
 
+/* Displayport compliance - internal modeset function */
+static int
+intel_dp_set_mode_for_compliance(struct intel_dp* intel_dp,
+								 struct drm_display_mode *comp_mode)
+{
+	int status = 0;
+	/* FIXME: Implementation TBD - necessary for DP compliance */
+	return status;
+}
+
+/* Displayport compliance - find the correct display mode */
+static struct drm_display_mode*
+intel_dp_get_compliance_mode(struct intel_dp *intel_dp, dp_compliance_mode compliance_mode)
+{
+	struct drm_display_mode *found_mode = NULL;
+	struct drm_connector *connector = &intel_dp->attached_connector->base;
+	int mode_count = 0;
+	char *comp_mode_string = NULL;
+
+	switch (compliance_mode) {
+		case DP_COMPLIANCE_MODE_FAILSAFE:
+			/* Failsafe is 640x480 @ 60Hz, 6bpc */
+			list_for_each_entry(found_mode, &connector->probed_modes, head) {
+				if (found_mode->hdisplay == 640 &&
+					   found_mode->vdisplay == 480 &&
+					   found_mode->vrefresh == 60) {
+					   // Found the failsafe mode, return it
+					   DRM_DEBUG_KMS("Displayport: Found failsafe mode '%s'\n",
+									 found_mode->name);
+					   goto exit_with_mode;
+				}
+				mode_count++;
+			}
+			comp_mode_string = "Failsafe";
+			break;
+		case DP_COMPLIANCE_MODE_PREFERRED:
+			list_for_each_entry(found_mode, &connector->probed_modes, head) {
+				// Check for a preferred mode
+				if (found_mode->type & DRM_MODE_TYPE_PREFERRED) {
+					   // Found the preferred mode, return it
+					   DRM_DEBUG_KMS("Displayport: Found preferred mode '%s'\n",
+									 found_mode->name);
+					   goto exit_with_mode;
+				}
+				mode_count++;
+			}
+			comp_mode_string = "Preferred";
+			break;
+		default:
+			DRM_DEBUG_KMS("Displayport: Invalid compliance mode type specified\n");
+			break;
+	}
+	/* No mode found, report the error */
+	DRM_DEBUG_KMS("Displayport: Could not find %s mode in %d modes\n", comp_mode_string, mode_count);
+
+exit_with_mode:
+	return found_mode;
+}
+
 /* Displayport compliance testing - Link training */
 static uint8_t
 intel_dp_autotest_link_training(struct intel_dp *intel_dp)
@@ -3362,30 +3430,48 @@  intel_dp_autotest_edid(struct intel_dp *intel_dp)
 	dp_compliance_mode comp_mode_type = DP_COMPLIANCE_MODE_PREFERRED;
 	int mode_count = 0;
 
+	DRM_DEBUG_KMS("Displayport: EDID automated test\n");
+
+	/* FIXME: Need a complete DPCD read here
+	          Need to read out branch device information */
+
+	/* Now read out the EDID */
 	edid_read = drm_get_edid(connector, adapter);
 
-	DRM_DEBUG_KMS("Displayport: EDID automated test\n");
+	/* FIXME: Need to determine how to detect E-DDC here */
+
 
 	if (edid_read) {
 		test_result = true;
 		edid_data = (uint8_t*) edid_read;
-		// Compute checksum
+		/* Compute checksum */
 		for (i = 0; i < 128; i++)
 				checksum += edid_data[i];
-
-		DRM_DEBUG_KMS("Displayport: EDID test - computed byte sum = %02x\n", checksum);
-		// Verify EDID checksum
+		/* Verify EDID checksum */
 		if (checksum % 256 == 0) {
 			/* Write the checksum to EDID checksum register */
 			ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TEST_EDID_CHECKSUM, &edid_read->checksum, 1);
-			// Reponse is ACK and and checksum written
+			/* Reponse is ACK and and checksum written */
 			test_result = DP_TEST_ACK | DP_TEST_EDID_CHECKSUM_WRITE;
 			DRM_DEBUG_KMS("Displayport: EDID test - checksum = %02x\n", edid_read->checksum);
 		}
 		else {
-			// Invalid checksum, set for failsafe mode
+			/* Invalid checksum - EDID corruption detection test */
+			DRM_DEBUG_KMS("Displayport: EDID test - checksum %02x invalid \n", edid_read->checksum);
 			comp_mode_type = DP_COMPLIANCE_MODE_FAILSAFE;
 		}
+
+		mode_count = intel_connector_update_modes(connector, edid_read);
+
+		if (!mode_count)
+			DRM_DEBUG_KMS("Displayport: Mode update failed\n");
+		else
+			DRM_DEBUG_KMS("Displayport: Added %d modes\n", mode_count);
+
+		/* Get the correct mode for this compliance test*/
+		use_mode = intel_dp_get_compliance_mode(intel_dp, comp_mode_type);
+		/* Set the mode */
+		intel_dp_set_mode_for_compliance(intel_dp, use_mode);
 	}
         return test_result;
 }