@@ -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;
}
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(-)