[igt-dev] [PATCH i-g-t v2 3/6] lib/igt_edid: add hdmi_vsdb

Simon Ser simon.ser at intel.com
Wed Jul 3 12:02:23 UTC 2019


The HDMI Vendor-Specific Data Block, defined as an opaque blob in the EDID
spec, is described in the HDMI 1.4 spec.

Most of the extension fields are optional, so it doesn't translate well to a C
struct. For now callers need to manually fill the hdmi_vsdb.data field.

Signed-off-by: Simon Ser <simon.ser at intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
 lib/igt_edid.c | 36 ++++++++++++++++++++++++++++--------
 lib/igt_edid.h | 50 +++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 75 insertions(+), 11 deletions(-)

diff --git a/lib/igt_edid.c b/lib/igt_edid.c
index df5b6611e22c..096668e68956 100644
--- a/lib/igt_edid.c
+++ b/lib/igt_edid.c
@@ -42,6 +42,8 @@ static const char monitor_range_padding[] = {
 	0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
 };
 
+const uint8_t hdmi_ieee_oui[3] = {0x03, 0x0C, 0x00};
+
 /* vfreq is in Hz */
 static void std_timing_set(struct std_timing *st, int hsize, int vfreq,
 			   enum std_timing_aspect aspect)
@@ -321,21 +323,23 @@ void cea_sad_init_pcm(struct cea_sad *sad, int channels,
  */
 const struct cea_vsdb *cea_vsdb_get_hdmi_default(size_t *size)
 {
-	static char raw[sizeof(struct cea_vsdb) + 4] = {0};
+	/* We'll generate a VSDB with 2 extension fields. */
+	static char raw[CEA_VSDB_HDMI_MIN_SIZE + 2] = {0};
 	struct cea_vsdb *vsdb;
+	struct hdmi_vsdb *hdmi;
 
 	*size = sizeof(raw);
 
 	/* Magic incantation. Works better if you orient your screen in the
 	 * direction of the VESA headquarters. */
 	vsdb = (struct cea_vsdb *) raw;
-	vsdb->ieee_oui[0] = 0x03;
-	vsdb->ieee_oui[1] = 0x0C;
-	vsdb->ieee_oui[2] = 0x00;
-	vsdb->data[0] = 0x10;
-	vsdb->data[1] = 0x00;
-	vsdb->data[2] = 0x38;
-	vsdb->data[3] = 0x2D;
+	memcpy(vsdb->ieee_oui, hdmi_ieee_oui, sizeof(hdmi_ieee_oui));
+	hdmi = &vsdb->data.hdmi;
+	hdmi->src_phy_addr[0] = 0x10;
+	hdmi->src_phy_addr[1] = 0x00;
+	/* 2 VSDB extension fields */
+	hdmi->flags1 = 0x38;
+	hdmi->max_tdms_clock = 0x2D;
 
 	return vsdb;
 }
@@ -371,6 +375,22 @@ size_t edid_cea_data_block_set_vsdb(struct edid_cea_data_block *block,
 	return sizeof(struct edid_cea_data_block) + vsdb_size;
 }
 
+size_t edid_cea_data_block_set_hdmi_vsdb(struct edid_cea_data_block *block,
+					 const struct hdmi_vsdb *hdmi,
+					 size_t hdmi_size)
+{
+	char raw_vsdb[CEA_VSDB_HDMI_MAX_SIZE] = {0};
+	struct cea_vsdb *vsdb = (struct cea_vsdb *) raw_vsdb;
+
+	assert(hdmi_size >= HDMI_VSDB_MIN_SIZE &&
+	       hdmi_size <= HDMI_VSDB_MAX_SIZE);
+	memcpy(vsdb->ieee_oui, hdmi_ieee_oui, sizeof(hdmi_ieee_oui));
+	memcpy(&vsdb->data.hdmi, hdmi, hdmi_size);
+
+	return edid_cea_data_block_set_vsdb(block, vsdb,
+					    CEA_VSDB_HEADER_SIZE + hdmi_size);
+}
+
 size_t edid_cea_data_block_set_speaker_alloc(struct edid_cea_data_block *block,
 					     const struct cea_speaker_alloc *speakers)
 {
diff --git a/lib/igt_edid.h b/lib/igt_edid.h
index 6fcb50a3e95e..7907baee08a9 100644
--- a/lib/igt_edid.h
+++ b/lib/igt_edid.h
@@ -191,11 +191,52 @@ struct cea_sad {
 	uint8_t bitrate;
 } __attribute__((packed));
 
+enum hdmi_vsdb_flags1 {
+	HDMI_VSDB_DVI_DUAL = 1 << 0,
+	HDMI_VSDB_DC_Y444 = 1 << 3, /* supports YCbCr 4:4:4 */
+	HDMI_VSDB_DC_30BIT = 1 << 4, /* 30 bits per pixel */
+	HDMI_VSDB_DC_36BIT = 1 << 5, /* 36 bits per pixel */
+	HDMI_VSDB_DC_48BIT = 1 << 6, /* 48 bits per pixel */
+	HDMI_VSDB_SUPPORTS_AI = 1 << 7, /* supports ACP, ISRC1 or ISRC2 packets */
+};
+
+enum hdmi_vsdb_flags2 {
+	HDMI_VSDB_CNC_GRAPHICS = 1 << 0,
+	HDMI_VSDB_CNC_PHOTO = 1 << 1,
+	HDMI_VSDB_CNC_CINEMA = 1 << 2,
+	HDMI_VSDB_CNC_GAME = 1 << 3,
+	HDMI_VSDB_VIDEO_PRESENT = 1 << 5,
+	HDMI_VSDB_INTERLACED_LATENCY_PRESENT = 1 << 6,
+	HDMI_VSDB_LATENCY_PRESENT = 1 << 7,
+};
+
+/* HDMI's IEEE Registration Identifier */
+extern const uint8_t hdmi_ieee_oui[3];
+
+/* HDMI Vendor-Specific Data Block (defined in the HDMI spec) */
+struct hdmi_vsdb {
+	uint8_t src_phy_addr[2]; /* source physical address */
+
+	/* Extension fields */
+	uint8_t flags1; /* enum hdmi_vsdb_flags1 */
+	uint8_t max_tdms_clock; /* multiply by 5MHz */
+	uint8_t flags2; /* enum hdmi_vsdb_flags2 */
+	char data[]; /* latency, misc, VIC, 3D */
+} __attribute__((packed));
+
+#define HDMI_VSDB_MIN_SIZE 2 /* just the source physical address */
+#define HDMI_VSDB_MAX_SIZE 28
+#define CEA_VSDB_HEADER_SIZE 3 /* IEEE OUI */
+#define CEA_VSDB_HDMI_MIN_SIZE (CEA_VSDB_HEADER_SIZE + HDMI_VSDB_MIN_SIZE)
+#define CEA_VSDB_HDMI_MAX_SIZE (CEA_VSDB_HEADER_SIZE + HDMI_VSDB_MAX_SIZE)
+
 /* Vendor-Specific Data Block */
 struct cea_vsdb {
-	uint8_t ieee_oui[3];
-	char data[];
-};
+	uint8_t ieee_oui[3]; /* 24-bit IEEE Registration Identifier, LSB */
+	union {
+		struct hdmi_vsdb hdmi;
+	} data;
+} __attribute__((packed));
 
 enum cea_speaker_alloc_item {
 	CEA_SPEAKER_FRONT_LEFT_RIGHT = 1 << 0,
@@ -315,6 +356,9 @@ size_t edid_cea_data_block_set_sad(struct edid_cea_data_block *block,
 				   const struct cea_sad *sads, size_t sads_len);
 size_t edid_cea_data_block_set_vsdb(struct edid_cea_data_block *block,
 				   const struct cea_vsdb *vsdb, size_t vsdb_size);
+size_t edid_cea_data_block_set_hdmi_vsdb(struct edid_cea_data_block *block,
+					 const struct hdmi_vsdb *hdmi,
+					 size_t hdmi_size);
 size_t edid_cea_data_block_set_speaker_alloc(struct edid_cea_data_block *block,
 					     const struct cea_speaker_alloc *speakers);
 void edid_ext_set_cea(struct edid_ext *ext, size_t data_blocks_size,
-- 
2.22.0



More information about the igt-dev mailing list