Blob Blame History Raw
diff --git a/src/atombios_output.c b/src/atombios_output.c
index 49de04f..544c4c4 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -374,6 +374,61 @@ atombios_output_digital_setup(xf86OutputPtr output, int device, DisplayModePtr m
     return ATOM_NOT_IMPLEMENTED;
 }
 
+/* lame.  this should go in the server. */
+static int
+atombios_maybe_hdmi_mode(xf86OutputPtr output)
+{
+    int i = 0, version, offset;
+    char *edid = NULL;
+#ifndef EDID_COMPLETE_RAWDATA
+    /* there's no getting this right unless we have complete EDID */
+    return ATOM_ENCODER_MODE_HDMI;
+#else
+    if (output->MonInfo)
+	return ATOM_ENCODER_MODE_DVI;
+
+    if (!(output->MonInfo->flags & EDID_COMPLETE_RAWDATA))
+	return ATOM_ENCODER_MODE_DVI;
+
+    if (!output->MonInfo->no_sections)
+	return ATOM_ENCODER_MODE_DVI;
+
+    edid = (char *)output->MonInfo->rawData;
+    if (!edid)
+	return ATOM_ENCODER_MODE_DVI;
+
+    /* find the CEA extension block */
+    for (i = 0; i < output->MonInfo->no_sections; i++)
+	if (edid[i * 128] == 0x02)
+	    break;
+    if (i == output->MonInfo->no_sections)
+	return ATOM_ENCODER_MODE_DVI;
+    edid += (i * 128);
+
+    version = edid[1];
+    offset = edid[2];
+    if (version < 3 || offset < 4)
+	return ATOM_ENCODER_MODE_DVI;
+
+    /* walk the cea data blocks */
+    for (i = 4; i < offset; i += (edid[i] & 0x1f) + 1) {
+	char *x = edid + i;
+
+	/* find a vendor specific block */
+	if ((x[0] & 0xe0) >> 5 == 0x03) {
+	    int oui = (x[3] << 16) + (x[2] << 8) + x[1];
+
+	    /* find the HDMI vendor OUI */
+	    if (oui == 0x000c03)
+		return ATOM_ENCODER_MODE_HDMI;
+	}
+    }
+
+    /* guess it's not HDMI after all */
+    return ATOM_ENCODER_MODE_DVI;
+#endif
+}
+
 static int
 atombios_output_dig1_setup(xf86OutputPtr output, DisplayModePtr mode)
 {
@@ -405,7 +460,7 @@ atombios_output_dig1_setup(xf86OutputPtr output, DisplayModePtr mode)
     if (OUTPUT_IS_DVI)
 	disp_data.ucEncoderMode = ATOM_ENCODER_MODE_DVI;
     else if (radeon_output->type == OUTPUT_HDMI)
-	disp_data.ucEncoderMode = ATOM_ENCODER_MODE_HDMI;
+	disp_data.ucEncoderMode = atombios_maybe_hdmi_mode(output);
     else if (radeon_output->type == OUTPUT_DP)
 	disp_data.ucEncoderMode = ATOM_ENCODER_MODE_DP;
     else if (radeon_output->type == OUTPUT_LVDS)