Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 2 Apr 2016 16:53:12 +0000 (UTC)
From:      Jared McNeill <jmcneill@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r297514 - head/sys/arm/allwinner
Message-ID:  <201604021653.u32GrChr061267@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jmcneill
Date: Sat Apr  2 16:53:12 2016
New Revision: 297514
URL: https://svnweb.freebsd.org/changeset/base/297514

Log:
  Improve HDMI display detection by searching the CEA-861 extension block for
  an HDMI vendor-specific data block (VSDB) containing the HDMI 24-bit IEEE
  registration ID (0x000C03).
  
  Approved by:	gonzo (mentor)

Modified:
  head/sys/arm/allwinner/a10_hdmi.c

Modified: head/sys/arm/allwinner/a10_hdmi.c
==============================================================================
--- head/sys/arm/allwinner/a10_hdmi.c	Sat Apr  2 16:25:46 2016	(r297513)
+++ head/sys/arm/allwinner/a10_hdmi.c	Sat Apr  2 16:53:12 2016	(r297514)
@@ -195,6 +195,15 @@ __FBSDID("$FreeBSD$");
 #define	CEA_TAG_ID		0x02
 #define	CEA_DTD			0x03
 #define	DTD_BASIC_AUDIO		(1 << 6)
+#define	CEA_REV			0x02
+#define	CEA_DATA_OFF		0x03
+#define	CEA_DATA_START		4
+#define	BLOCK_TAG(x)		(((x) >> 5) & 0x7)
+#define	BLOCK_TAG_VSDB		3
+#define	BLOCK_LEN(x)		((x) & 0x1f)
+#define	HDMI_VSDB_MINLEN	5
+#define	HDMI_OUI		"\x03\x0c\x00"
+#define	HDMI_OUI_LEN		3
 
 struct a10hdmi_softc {
 	struct resource		*res;
@@ -372,6 +381,41 @@ a10hdmi_ddc_read(struct a10hdmi_softc *s
 	return (0);
 }
 
+static int
+a10hdmi_detect_hdmi_vsdb(uint8_t *edid)
+{
+	int off, p, btag, blen;
+
+	if (edid[EXT_TAG] != CEA_TAG_ID)
+		return (0);
+
+	off = edid[CEA_DATA_OFF];
+
+	/* CEA data block collection starts at byte 4 */
+	if (off <= CEA_DATA_START)
+		return (0);
+
+	/* Parse the CEA data blocks */
+	for (p = CEA_DATA_START; p < off;) {
+		btag = BLOCK_TAG(edid[p]);
+		blen = BLOCK_LEN(edid[p]);
+
+		/* Make sure the length is sane */
+		if (p + blen + 1 > off)
+			break;
+
+		/* Look for a VSDB with the HDMI 24-bit IEEE registration ID */
+		if (btag == BLOCK_TAG_VSDB && blen >= HDMI_VSDB_MINLEN &&
+		    memcmp(&edid[p + 1], HDMI_OUI, HDMI_OUI_LEN) == 0)
+			return (1);
+
+		/* Next data block */
+		p += (1 + blen);
+	}
+
+	return (0);
+}
+
 static void
 a10hdmi_detect_hdmi(struct a10hdmi_softc *sc, int *phdmi, int *paudio)
 {
@@ -389,7 +433,7 @@ a10hdmi_detect_hdmi(struct a10hdmi_softc
 		if (a10hdmi_ddc_read(sc, block, edid) != 0)
 			return;
 
-		if (edid[EXT_TAG] == CEA_TAG_ID) {
+		if (a10hdmi_detect_hdmi_vsdb(edid) != 0) {
 			*phdmi = 1;
 			*paudio = ((edid[CEA_DTD] & DTD_BASIC_AUDIO) != 0);
 			return;
@@ -518,6 +562,9 @@ a10hdmi_set_videomode(device_t dev, cons
 	    PLLCTRL0_VCO_S);
 
 	/* Setup display settings */
+	if (bootverbose)
+		device_printf(dev, "HDMI: %s, Audio: %s\n",
+		    sc->has_hdmi ? "yes" : "no", sc->has_audio ? "yes" : "no");
 	val = 0;
 	if (sc->has_hdmi)
 		val |= VID_CTRL_HDMI_MODE;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201604021653.u32GrChr061267>