diff options
Diffstat (limited to 'common/edid.c')
-rw-r--r-- | common/edid.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/common/edid.c b/common/edid.c index e08e420920..19410aa4fc 100644 --- a/common/edid.c +++ b/common/edid.c @@ -85,6 +85,7 @@ static void decode_timing(u8 *buf, struct display_timing *timing) uint x_mm, y_mm; unsigned int ha, hbl, hso, hspw, hborder; unsigned int va, vbl, vso, vspw, vborder; + struct edid_detailed_timing *t = (struct edid_detailed_timing *)buf; /* Edid contains pixel clock in terms of 10KHz */ set_entry(&timing->pixelclock, (buf[0] + (buf[1] << 8)) * 10000); @@ -111,6 +112,19 @@ static void decode_timing(u8 *buf, struct display_timing *timing) set_entry(&timing->vback_porch, vbl - vso - vspw); set_entry(&timing->vsync_len, vspw); + timing->flags = 0; + if (EDID_DETAILED_TIMING_FLAG_HSYNC_POLARITY(*t)) + timing->flags |= DISPLAY_FLAGS_HSYNC_HIGH; + else + timing->flags |= DISPLAY_FLAGS_HSYNC_LOW; + if (EDID_DETAILED_TIMING_FLAG_VSYNC_POLARITY(*t)) + timing->flags |= DISPLAY_FLAGS_VSYNC_HIGH; + else + timing->flags |= DISPLAY_FLAGS_VSYNC_LOW; + + if (EDID_DETAILED_TIMING_FLAG_INTERLACED(*t)) + timing->flags = DISPLAY_FLAGS_INTERLACED; + debug("Detailed mode clock %u Hz, %d mm x %d mm\n" " %04x %04x %04x %04x hborder %x\n" " %04x %04x %04x %04x vborder %x\n", @@ -122,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) { @@ -167,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; } |