summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/edid.c42
-rw-r--r--include/edid.h14
-rw-r--r--include/fdtdec.h1
3 files changed, 57 insertions, 0 deletions
diff --git a/common/edid.c b/common/edid.c
index ab7069fdcd..19410aa4fc 100644
--- a/common/edid.c
+++ b/common/edid.c
@@ -136,6 +136,39 @@ static void decode_timing(u8 *buf, struct display_timing *timing)
va + vbl, vborder);
}
+/**
+ * Check if HDMI vendor specific data block is present in CEA block
+ * @param info CEA extension block
+ * @return true if block is found
+ */
+static bool cea_is_hdmi_vsdb_present(struct edid_cea861_info *info)
+{
+ u8 end, i = 0;
+
+ /* check for end of data block */
+ end = info->dtd_offset;
+ if (end == 0)
+ end = 127;
+ if (end < 4 || end > 127)
+ return false;
+ end -= 4;
+
+ while (i < end) {
+ /* Look for vendor specific data block of appropriate size */
+ if ((EDID_CEA861_DB_TYPE(*info, i) == EDID_CEA861_DB_VENDOR) &&
+ (EDID_CEA861_DB_LEN(*info, i) >= 5)) {
+ u8 *db = &info->data[i + 1];
+ u32 oui = db[0] | (db[1] << 8) | (db[2] << 16);
+
+ if (oui == HDMI_IEEE_OUI)
+ return true;
+ }
+ i += EDID_CEA861_DB_LEN(*info, i) + 1;
+ }
+
+ return false;
+}
+
int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing,
int *panel_bits_per_colourp)
{
@@ -181,6 +214,15 @@ int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing,
((edid->video_input_definition & 0x70) >> 3) + 4;
}
+ timing->hdmi_monitor = false;
+ if (edid->extension_flag && (buf_size >= EDID_EXT_SIZE)) {
+ struct edid_cea861_info *info =
+ (struct edid_cea861_info *)(buf + sizeof(*edid));
+
+ if (info->extension_tag == EDID_CEA861_EXTENSION_TAG)
+ timing->hdmi_monitor = cea_is_hdmi_vsdb_present(info);
+ }
+
return 0;
}
diff --git a/include/edid.h b/include/edid.h
index 8b022fa98a..a9f2f3d3ab 100644
--- a/include/edid.h
+++ b/include/edid.h
@@ -19,6 +19,9 @@
#define EDID_SIZE 128
#define EDID_EXT_SIZE 256
+/* OUI of HDMI vendor specific data block */
+#define HDMI_IEEE_OUI 0x000c03
+
#define GET_BIT(_x, _pos) \
(((_x) >> (_pos)) & 1)
#define GET_BITS(_x, _pos_msb, _pos_lsb) \
@@ -234,6 +237,13 @@ struct edid1_info {
unsigned char checksum;
} __attribute__ ((__packed__));
+enum edid_cea861_db_types {
+ EDID_CEA861_DB_AUDIO = 0x01,
+ EDID_CEA861_DB_VIDEO = 0x02,
+ EDID_CEA861_DB_VENDOR = 0x03,
+ EDID_CEA861_DB_SPEAKER = 0x04,
+};
+
struct edid_cea861_info {
unsigned char extension_tag;
#define EDID_CEA861_EXTENSION_TAG 0x02
@@ -251,6 +261,10 @@ struct edid_cea861_info {
#define EDID_CEA861_DTD_COUNT(_x) \
GET_BITS(((_x).dtd_count), 3, 0)
unsigned char data[124];
+#define EDID_CEA861_DB_TYPE(_x, offset) \
+ GET_BITS((_x).data[offset], 7, 5)
+#define EDID_CEA861_DB_LEN(_x, offset) \
+ GET_BITS((_x).data[offset], 4, 0)
} __attribute__ ((__packed__));
/**
diff --git a/include/fdtdec.h b/include/fdtdec.h
index b0e5b2767d..3000ecbb58 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -967,6 +967,7 @@ struct display_timing {
struct timing_entry vsync_len; /* ver. sync len */
enum display_flags flags; /* display flags */
+ bool hdmi_monitor; /* is hdmi monitor? */
};
/**