summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/igt_edid.c36
-rw-r--r--lib/igt_edid.h50
2 files changed, 75 insertions, 11 deletions
diff --git a/lib/igt_edid.c b/lib/igt_edid.c
index df5b6611..096668e6 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 6fcb50a3..7907baee 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,