HDMI EDID详细解析——C代码实现

继上一篇《HDMI EDID详细解析》
https://blog.csdn.net/cfl927096306/article/details/108017501
现在用C代码来实现解析HDMI EDID的功能,详细如下

部分代码是参考了这两篇文章,非常感谢!
https://blog.csdn.net/yexiangCSDN/article/details/100040429
https://www.cnblogs.com/lsilkworm/archive/2010/06/04/1751474.html

parseEdid.h

#ifndef __PARSE_EDID_H__
#define __PARSE_EDID_H__

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include     // std::find + transform

using namespace std;

#define EDID_LENGTH 128
#define BLOCK0_DTD_START 0x36
#define BLOCK0_TOTAL_DTD 4
#define DTD_SIZE 18

#define UPPER_NIBBLE(x) (((128|64|32|16) & (x)) >> 4)
#define LOWER_NIBBLE(x) ((1|2|4|8) & (x))
#define COMBINE_HI_4LO(hi, lo) ((((unsigned)hi) << 4) | (unsigned)lo)
#define COMBINE_HI_8LO(hi, lo) ((((unsigned)hi) << 8) | (unsigned)lo)
#define PIXEL_CLOCK_LO     (unsigned)i_pDtd[ 0 ]
#define PIXEL_CLOCK_HI     (unsigned)i_pDtd[ 1 ]
#define PIXEL_CLOCK        (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*10000)
#define H_ACTIVE_LO        (unsigned)i_pDtd[ 2 ]
#define H_BLANKING_LO      (unsigned)i_pDtd[ 3 ]
#define H_ACTIVE_HI        UPPER_NIBBLE( (unsigned)i_pDtd[ 4 ] )
#define H_ACTIVE           COMBINE_HI_8LO( H_ACTIVE_HI, H_ACTIVE_LO )
#define H_BLANKING_HI      LOWER_NIBBLE( (unsigned)i_pDtd[ 4 ] )
#define H_BLANKING         COMBINE_HI_8LO( H_BLANKING_HI, H_BLANKING_LO )
#define V_ACTIVE_LO        (unsigned)i_pDtd[ 5 ]
#define V_BLANKING_LO      (unsigned)i_pDtd[ 6 ]
#define V_ACTIVE_HI        UPPER_NIBBLE( (unsigned)i_pDtd[ 7 ] )
#define V_ACTIVE           COMBINE_HI_8LO( V_ACTIVE_HI, V_ACTIVE_LO )
#define V_BLANKING_HI      LOWER_NIBBLE( (unsigned)i_pDtd[ 7 ] )
#define V_BLANKING         COMBINE_HI_8LO( V_BLANKING_HI, V_BLANKING_LO )
#define H_SYNC_OFFSET_LO   (unsigned)i_pDtd[ 8 ]
#define H_SYNC_WIDTH_LO    (unsigned)i_pDtd[ 9 ]
#define V_SYNC_OFFSET_LO   UPPER_NIBBLE( (unsigned)i_pDtd[ 10 ] )
#define V_SYNC_WIDTH_LO    LOWER_NIBBLE( (unsigned)i_pDtd[ 10 ] )
#define V_SYNC_WIDTH_HI    ((unsigned)i_pDtd[ 11 ] & (1|2))
#define V_SYNC_OFFSET_HI   (((unsigned)i_pDtd[ 11 ] & (4|8)) >> 2)
#define H_SYNC_WIDTH_HI    (((unsigned)i_pDtd[ 11 ] & (16|32)) >> 4)
#define H_SYNC_OFFSET_HI   (((unsigned)i_pDtd[ 11 ] & (64|128)) >> 6)
#define V_SYNC_WIDTH       COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
#define V_FRONT_PORCH      COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
#define H_SYNC_WIDTH       COMBINE_HI_4LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
#define H_FRONT_PORCH      COMBINE_HI_4LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
#define H_SIZE_LO          (unsigned)i_pDtd[ 12 ]
#define V_SIZE_LO          (unsigned)i_pDtd[ 13 ]
#define H_SIZE_HI          UPPER_NIBBLE( (unsigned)i_pDtd[ 14 ] )
#define V_SIZE_HI          LOWER_NIBBLE( (unsigned)i_pDtd[ 14 ] )
#define H_SIZE             COMBINE_HI_8LO( H_SIZE_HI, H_SIZE_LO )
#define V_SIZE             COMBINE_HI_8LO( V_SIZE_HI, V_SIZE_LO )
#define H_BORDER           (unsigned)i_pDtd[ 15 ]
#define V_BORDER           (unsigned)i_pDtd[ 16 ]
#define FLAGS              (unsigned)i_pDtd[ 17 ]
#define INTERLACED         (FLAGS&128)
#define SYNC_TYPE          (FLAGS&3<<3)  /* bits 4,3 */
#define SYNC_SEPARATE      (3<<3)
#define HSYNC_POSITIVE     (FLAGS & 4)
#define VSYNC_POSITIVE     (FLAGS & 2)

// 列出一些常用的HDMI分辨率
typedef enum
{
    HDMI_VIC_VESA_TIMING = 0,
    HDMI_VIC_640X480P60 = 1,
    HDMI_VIC_720X480P60_4_3 = 2,
    HDMI_VIC_720X480P60_16_9 = 3,
    HDMI_VIC_1280X720P60 = 4,
    HDMI_VIC_1920X1080I60 = 5,
    HDMI_VIC_720X480I60_4_3 = 6,
    HDMI_VIC_720X480I60_16_9 = 7,
    HDMI_VIC_1920X1080P60 = 16,
    HDMI_VIC_720X576P50_4_3 = 17,
    HDMI_VIC_720X576P50_16_9 = 18,
    HDMI_VIC_1280X720P50 = 19,
    HDMI_VIC_1920X1080I50 = 20,
    HDMI_VIC_720X576I50_4_3 = 21,
    HDMI_VIC_720X576I50_16_9 = 22,
    HDMI_VIC_1920X1080P50 = 31,
    HDMI_VIC_1920X1080P24 = 32,
    HDMI_VIC_1920X1080P25 = 33,
    HDMI_VIC_1920X1080P30 = 34,
    HDMI_VIC_3840X2160P24 = 93,
    HDMI_VIC_3840X2160P25 = 94,
    HDMI_VIC_3840X2160P30 = 95,
    HDMI_VIC_3840X2160P50 = 96,
    HDMI_VIC_3840X2160P60 = 97,
    HDMI_VIC_4096X2160P24 = 98,
    HDMI_VIC_4096X2160P25 = 99,
    HDMI_VIC_4096X2160P30 = 100,
    HDMI_VIC_4096X2160P50 = 101,
    HDMI_VIC_4096X2160P60 = 102,

    VESA_800X600P60 = 1000, // fixme
    VESA_1024X768P60,
    VESA_1280X768P60,
    VESA_1280X800P60,
    VESA_1280X960P60,
    VESA_1280X1024P60,
    VESA_1360X768P60,
    VESA_1366X768P60,
    VESA_1400X1050P60,
    VESA_1440X900P60,
    VESA_1600X900P60,
    VESA_1600X1200P60,
    VESA_1680X1050P60,
    VESA_1920X1200P60,
    VESA_2560X1600P60,
} E_Timing;

typedef enum
{
    HDMI_4K_VIC_3840X2160P30 = 1,
    HDMI_4K_VIC_3840X2160P25 = 2,
    HDMI_4K_VIC_3840X2160P24 = 3,
    HDMI_4K_VIC_4096X2160P24 = 4
} E_Hdmi4kVic;

typedef enum
{
    HDMI_3D_FORMAT_FRAME_PACKING = 0x01,
    HDMI_3D_FORMAT_FIELD_ALTERNATIVE = 0x02,
    HDMI_3D_FORMAT_LINE_ALTERNATIVE = 0x04,
    HDMI_3D_FORMAT_SIDE_BY_SIDE_FULL = 0x08,
    HDMI_3D_FORMAT_L_DEPTH = 0x10,
    HDMI_3D_FORMAT_L_DEPTH_GRAPHICS = 0x20,
    HDMI_3D_FORMAT_TOP_AND_BOTTOM = 0x40,
    HDMI_3D_FORMAT_SIDE_BY_SIDE_HALF_HORZ = 0x100,
    HDMI_3D_FORMAT_SIDE_BY_SIDE_HALF_ALL = 0x8000
} E_Hdmi3dFormat;

typedef enum
{
    AUDIO_FORMAT_NONE = 0,
    AUDIO_FORMAT_PCM,
    AUDIO_FORMAT_AC3,
    AUDIO_FORMAT_MPEG1,
    AUDIO_FORMAT_MP3,
    AUDIO_FORMAT_MPEG2,
    AUDIO_FORMAT_AAC,
    AUDIO_FORMAT_DTS,
    AUDIO_FORMAT_ATRAC,
    AUDIO_FORMAT_ONE_BIT_AUDIO,
    AUDIO_FORMAT_DOLBY,
    AUDIO_FORMAT_DTS_HD,
    AUDIO_FORMAT_MAT,
    AUDIO_FORMAT_DST,
    AUDIO_FORMAT_WMA_PRO,
} E_AudioFormat;

typedef enum
{
    AUDIO_SAMPLE_RATE_32K  = 0x01, // 32K
    AUDIO_SAMPLE_RATE_44K  = 0x02, // 44.1K
    AUDIO_SAMPLE_RATE_48K  = 0x04, // 48K
    AUDIO_SAMPLE_RATE_88K  = 0x08, // 88.2K
    AUDIO_SAMPLE_RATE_96K  = 0x10, // 96K
    AUDIO_SAMPLE_RATE_176K = 0x20, // 176.4K
    AUDIO_SAMPLE_RATE_192K = 0x40, // 192K
} E_AudioSampleRate;

typedef enum
{
    AUDIO_SAMPLE_SIZE_16BIT = 0x01,
    AUDIO_SAMPLE_SIZE_20BIT = 0x02,
    AUDIO_SAMPLE_SIZE_24BIT = 0x04,
} E_AudioSampleSize;

typedef enum
{
    CEA_TAG_ADB  = 1, // Audio Data Block
    CEA_TAG_VDB  = 2, // Video Data Block
    CEA_TAG_VSDB = 3, // Vendor-Specific Data Block
    CEA_TAG_SPK  = 4, // Speaker Allocation Data Block
    CEA_TAG_DTC  = 5, // VESA Display Transfer Characteristic Data Block
    CEA_TAG_EXT  = 7, // Use Extended Tag
} E_CeaDataBlockTag;

typedef enum
{
    CEA_EXT_TAG_VCDB     = 0,  // Video Capability Data Block
    CEA_EXT_TAG_VSVDB    = 1,  // Vendor-Specific Video Data Block
    CEA_EXT_TAG_DDDB     = 2,  // VESA Display Device Data Block
    CEA_EXT_TAG_VTDB     = 3,  // VESA Video Timing Block Extension
    CEA_EXT_TAG_CDB      = 5,  // Colorimetry Data Block
    CEA_EXT_TAG_HDR      = 6,  // HDR Static Metadata Data Block
    CEA_EXT_TAG_VFPDB    = 13, // Video Format Preference Data Block
    CEA_EXT_TAG_Y420VDB  = 14, // YCBCR 4:2:0 Video Data Block
    CEA_EXT_TAG_Y420CMDB = 15, // YCBCR 4:2:0 Capability Map Data Block
    CEA_EXT_TAG_VSADB    = 17, // Vendor-Specific Audio Data Block
    CEA_EXT_TAG_IDB      = 32, // InfoFrame Data Block
} E_CeaExtDataBlockTag;

typedef enum
{
    HDMI_DEEP_COLOR_8BIT = 0,
    HDMI_DEEP_COLOR_10BIT,
    HDMI_DEEP_COLOR_12BIT,
    HDMI_DEEP_COLOR_16BIT
} E_HdmiDeepColorType;

typedef enum
{
    HDMI_XV_YCC601 = 0x01,
    HDMI_XV_YCC709 = 0x02,
    HDMI_S_YCC601 = 0x04,
    HDMI_ADOBE_YCC601 = 0x08,
    HDMI_ADOBE_RGB = 0x10,
    HDMI_BT2020_C_YCC = 0x20,
    HDMI_BT2020_YCC = 0x40,
    HDMI_BT2020_RGB = 0x80
} E_HdmiColorimetry;

typedef enum {
    PRODUCT_SERIAL_NUMBER = 0xFF,
    ASCII_DATA_STRING = 0xFE,
    RANGE_LIMITS = 0xFD,
    MONITOR_NAME = 0xFC,
    COLOR_POINT_DATA = 0xFB,
    STANDART_TIMING = 0xFA,
    DISPLAY_COLOR_MANAGEMENT = 0xF9,
    CVT_TIMING_CODES = 0xF8,
    ESTABLISHED_TIMINGS_III = 0xF7,
    DUMMY_DESCRIPTOR = 0x10,
    MANUFACTURER_SPECIFIED_DISPLAY = 0x0F,
    DETAILED_TIMING_DEFINITION = 0x00,
    UNKNOW_DESCRIPTOR = -1,
} E_DisplayDescriptor;

#define AUDIO_FORMAT(i) ( \
    (i == AUDIO_FORMAT_PCM)           ? "PCM" : \
    (i == AUDIO_FORMAT_AC3)           ? "AC3" : \
    (i == AUDIO_FORMAT_MPEG1)         ? "MPEG1" : \
    (i == AUDIO_FORMAT_MP3)           ? "MP3" : \
    (i == AUDIO_FORMAT_MPEG2)         ? "MPEG2" : \
    (i == AUDIO_FORMAT_AAC)           ? "AAC" : \
    (i == AUDIO_FORMAT_DTS)           ? "DTS" : \
    (i == AUDIO_FORMAT_ATRAC)         ? "ATRAC" : \
    (i == AUDIO_FORMAT_ONE_BIT_AUDIO) ? "ONE_BIT_AUDIO" : \
    (i == AUDIO_FORMAT_DOLBY)         ? "DOLBY" : \
    (i == AUDIO_FORMAT_DTS_HD)        ? "DTS_HD" : \
    (i == AUDIO_FORMAT_MAT)           ? "MAT" : \
    (i == AUDIO_FORMAT_DST)           ? "DST" : \
    (i == AUDIO_FORMAT_WMA_PRO)       ? "WMA_PRO" : "None")

#define SAMPLE_RATE(i) ( \
    (i == AUDIO_SAMPLE_RATE_32K)  ? "32K" : \
    (i == AUDIO_SAMPLE_RATE_44K)  ? "44.1K" : \
    (i == AUDIO_SAMPLE_RATE_48K)  ? "48K" : \
    (i == AUDIO_SAMPLE_RATE_88K)  ? "88.2K" : \
    (i == AUDIO_SAMPLE_RATE_96K)  ? "96K" : \
    (i == AUDIO_SAMPLE_RATE_176K) ? "176.4K" : \
    (i == AUDIO_SAMPLE_RATE_192K) ? "192K" : "None")

#define DEEP_COLOR(i) ( \
    (i == HDMI_DEEP_COLOR_8BIT)  ? "8BIT" : \
    (i == HDMI_DEEP_COLOR_10BIT) ? "10BIT" : \
    (i == HDMI_DEEP_COLOR_12BIT) ? "12BIT" : \
    (i == HDMI_DEEP_COLOR_16BIT) ? "16BIT" : "None")

#define HDMI_4K_VIC(i) ( \
    (i == HDMI_4K_VIC_3840X2160P30) ? "3840x2160p@30" : \
    (i == HDMI_4K_VIC_3840X2160P25) ? "3840x2160p@25" : \
    (i == HDMI_4K_VIC_3840X2160P24) ? "3840x2160p@24" : \
    (i == HDMI_4K_VIC_4096X2160P24) ? "4096x2160p@24" : "None")

#define HDMI_3D_FORMAT(i) ( \
    (i == HDMI_3D_FORMAT_FRAME_PACKING)          ? "FramePacking" : \
    (i == HDMI_3D_FORMAT_FIELD_ALTERNATIVE)      ? "FieldAlternative" : \
    (i == HDMI_3D_FORMAT_LINE_ALTERNATIVE)       ? "LineAlternative" : \
    (i == HDMI_3D_FORMAT_SIDE_BY_SIDE_FULL)      ? "SideBySide(Full)" : \
    (i == HDMI_3D_FORMAT_L_DEPTH)                ? "L+Depth" : \
    (i == HDMI_3D_FORMAT_L_DEPTH_GRAPHICS)       ? "L+Depth+Graphics" : \
    (i == HDMI_3D_FORMAT_TOP_AND_BOTTOM)         ? "TopAndBottom" : \
    (i == HDMI_3D_FORMAT_SIDE_BY_SIDE_HALF_HORZ) ? "SideBySide(Half Horz)" : \
    (i == HDMI_3D_FORMAT_SIDE_BY_SIDE_HALF_ALL)  ? "SideBySide(Half All)" : "None")

#define HDMI_COLORIMETRY(i) ( \
    (i == HDMI_XV_YCC601)    ? "XVYCC-601" : \
    (i == HDMI_XV_YCC709)    ? "XVYCC-709" : \
    (i == HDMI_S_YCC601)     ? "sYCC-601" : \
    (i == HDMI_ADOBE_YCC601) ? "AdobeYCC-601" : \
    (i == HDMI_ADOBE_RGB)    ? "AdobeRGB" : \
    (i == HDMI_BT2020_C_YCC) ? "BT.2020-cYCC" : \
    (i == HDMI_BT2020_YCC)   ? "BT.2020-YCC" : \
    (i == HDMI_BT2020_RGB)   ? "BT.2020-RGB" : "None")

typedef struct
{
    E_AudioFormat eAudioFormat;
    unsigned char u8MaxChannels;
    unsigned char u8SampleRate; // Byte2
    unsigned char u8Byte3; // Byte3
} T_AudioDescriptor;

typedef struct
{
    // count of Short Audio Descriptors
    unsigned char u8Count;
    // up to 10 Short Audio Descriptors
    T_AudioDescriptor aSAD[10];
} T_EdidAudioData;

typedef struct
{
    // count of Short Video Descriptors
    unsigned char u8Count;
    // up to 32 Short Video Descriptors
    unsigned char aVic[32];
} T_EdidVideoData;

typedef struct
{
    unsigned int  u32MaxTmdsClock;
    unsigned char u8ScdcPresent;
    unsigned char u8RrCapable;
    unsigned char u8Lte340mScramble;
    unsigned char u8IndependentView;
    unsigned char u8DualView;
    unsigned char u83dOsd;
    unsigned char u8Dc16Bit420;
    unsigned char u8Dc12Bit420;
    unsigned char u8Dc10Bit420;
} T_Vsdb2Content;

typedef struct
{
    unsigned char u8PhyAddr0;
    unsigned char u8PhyAddr1;
    unsigned char u8DcSupport;
    unsigned int  u32MaxTmdsClock;
    unsigned char u8CnAndPresent;
    unsigned char u8VideoLatency;
    unsigned char u8AudioLatency;
    unsigned char u8IVideoLatency;
    unsigned char u8IAudioLatency;
    unsigned char u8HdmiVicLen;
    unsigned char u8Hdmi3dLen;
    unsigned char u8Hdmi4kVic[4];
    unsigned char u8ImageSizeAnd3dPresent;
    unsigned char u8ImageSizeFlag;
    unsigned char u8Support3D;
    unsigned char u83dStructAll15_8;
    unsigned char u83dStructAll7_0;
    unsigned char u83dVicSupportLen;
    unsigned char u83dVicSupport[16];
    unsigned char u83dOrderLen;
    unsigned short u163dOrder[16];
} T_Vsdb1Content;

typedef struct
{
    unsigned int u32HActive;
    unsigned int u32VActive;
    unsigned int u32ScanMode; // 0:progressive, 1:interlace
    unsigned int u32HTotal;
    unsigned int u32VTotal;
    unsigned int u32VFreq;
    unsigned int u32PixelClock;
} T_TimingInfo;

typedef struct
{
    int s32Vic; // 0 for VESA timing
    const char *pName;
    T_TimingInfo tTimingInfo;
} T_TimingMap;

#endif // __PARSE_EDID_H__

parseEdid.cpp,代码通俗易懂,看代码即可知道原理

#include "parseEdid.h"

T_EdidAudioData tAudioData;
T_EdidVideoData tVideoData;
T_Vsdb1Content tVsdb1;
T_Vsdb2Content tVsdb2;
unsigned char aHdrContent[2];
vector<E_Timing> aSupportTimings;

unsigned char aTestEdid[256] =
{
    0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x3b, 0x0d, 0x00, 0x06, 0x00, 0x01,
    0x01, 0x1a, 0x01, 0x03, 0x80, 0x59, 0x32, 0x78, 0x0a, 0x23, 0xad, 0xa4, 0x54, 0x4d, 0x99, 0x26,
    0x0f, 0x47, 0x4a, 0xbd, 0xef, 0x80, 0x71, 0x4f, 0x81, 0xc0, 0x81, 0x00, 0x81, 0x80, 0x95, 0x00,
    0xa9, 0xc0, 0xb3, 0x00, 0x01, 0x01, 0x08, 0xe8, 0x00, 0x30, 0xf2, 0x70, 0x5a, 0x80, 0xb0, 0x58,
    0x8a, 0x00, 0x50, 0x1d, 0x74, 0x00, 0x00, 0x1e, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40,
    0x58, 0x2c, 0x45, 0x00, 0x50, 0x1d, 0x74, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18,
    0x4b, 0x0f, 0x87, 0x3c, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
    0x00, 0x53, 0x41, 0x4d, 0x53, 0x55, 0x4e, 0x47, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x5c,
    0x02, 0x03, 0x50, 0xf0, 0x57, 0x61, 0x10, 0x1f, 0x04, 0x13, 0x05, 0x14, 0x20, 0x21, 0x22, 0x5d,
    0x5e, 0x5f, 0x60, 0x65, 0x66, 0x62, 0x63, 0x64, 0x07, 0x16, 0x03, 0x12, 0x29, 0x09, 0x07, 0x07,
    0x15, 0x07, 0x50, 0x3d, 0x04, 0xc0, 0x83, 0x01, 0x00, 0x00, 0xe2, 0x00, 0x0f, 0xe3, 0x05, 0xc3,
    0x01, 0x6e, 0x03, 0x0c, 0x00, 0x10, 0x00, 0xb8, 0x3c, 0x20, 0x10, 0x80, 0x01, 0x02, 0x03, 0x04,
    0x67, 0xd8, 0x5d, 0xc4, 0x01, 0x78, 0x80, 0x03, 0xe3, 0x06, 0x05, 0x01, 0xe3, 0x0f, 0x01, 0xe0,
    0x01, 0x1d, 0x80, 0xd0, 0x72, 0x1c, 0x16, 0x20, 0x10, 0x2c, 0x25, 0x80, 0x50, 0x1d, 0x74, 0x00,
    0x00, 0x9e, 0x66, 0x21, 0x56, 0xaa, 0x51, 0x00, 0x1e, 0x30, 0x46, 0x8f, 0x33, 0x00, 0x50, 0x1d,
    0x74, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb
};

// 比较常见的放在DTD的分辨率
// 参考 CEA-861-F 
unsigned int aDtd18Byte[][19] =
{
    {HDMI_VIC_640X480P60,      0xD5,0x09,0x80,0xA0,0x20,0xE0,0x2D,0x10,0x10,0x60,0xA2,0x00,0xC4,0x8E,0x21,0x00,0x00,0x18}, //640X480P60
    {HDMI_VIC_720X480I60_4_3,  0x8C,0x0A,0xA0,0x14,0x51,0xF0,0x16,0x00,0x26,0x7C,0x43,0x00,0x13,0x8E,0x21,0x00,0x00,0x98}, //480I60 4:3
    {HDMI_VIC_720X480I60_16_9, 0x8C,0x0A,0xA0,0x14,0x51,0xF0,0x16,0x00,0x26,0x7C,0x43,0x00,0xC4,0x8E,0x21,0x00,0x00,0x98}, //480I60 16:9
    {HDMI_VIC_720X576I50_4_3,  0x8C,0x0A,0xA0,0x20,0x51,0x20,0x18,0x10,0x18,0x7E,0x23,0x00,0x13,0x8E,0x21,0x00,0x00,0x98}, //576I50 4:3
    {HDMI_VIC_720X576I50_16_9, 0x8C,0x0A,0xA0,0x20,0x51,0x20,0x18,0x10,0x18,0x7E,0x23,0x00,0xC4,0x8E,0x21,0x00,0x00,0x98}, //576I50 16:9
    {HDMI_VIC_720X480P60_4_3,  0x8C,0x0A,0xD0,0x8A,0x20,0xE0,0x2D,0x10,0x10,0x3E,0x96,0x00,0x13,0x8E,0x21,0x00,0x00,0x18}, //480P60 4:3
    {HDMI_VIC_720X480P60_16_9, 0x8C,0x0A,0xD0,0x8A,0x20,0xE0,0x2D,0x10,0x10,0x3E,0x96,0x00,0xC4,0x8E,0x21,0x00,0x00,0x18}, //480P60 16:9
    {HDMI_VIC_720X576P50_4_3,  0x8C,0x0A,0xD0,0x90,0x20,0x40,0x31,0x20,0x0C,0x40,0x55,0x00,0x13,0x8E,0x21,0x00,0x00,0x18}, //576P50 4:3
    {HDMI_VIC_720X576P50_16_9, 0x8C,0x0A,0xD0,0x90,0x20,0x40,0x31,0x20,0x0C,0x40,0x55,0x00,0xC4,0x8E,0x21,0x00,0x00,0x18}, //576P50 16:9
    {HDMI_VIC_1280X720P50,     0x01,0x1D,0x00,0xBC,0x52,0xD0,0x1E,0x20,0xB8,0x28,0x55,0x40,0xC4,0x8E,0x21,0x00,0x00,0x1E}, //720P50
    {HDMI_VIC_1280X720P60,     0x01,0x1D,0x00,0x72,0x51,0xD0,0x1E,0x20,0x6E,0x28,0x55,0x00,0xC4,0x8E,0x21,0x00,0x00,0x1E}, //720P60
    {HDMI_VIC_1920X1080I50,    0x01,0x1D,0x80,0xD0,0x72,0x1C,0x16,0x20,0x10,0x2C,0x25,0x80,0xC4,0x8E,0x21,0x00,0x00,0x9E}, //1080I50
    {HDMI_VIC_1920X1080I60,    0x01,0x1D,0x80,0x18,0x71,0x1C,0x16,0x20,0x58,0x2C,0x25,0x00,0xC4,0x8E,0x21,0x00,0x00,0x9E}, //1080I60
    {HDMI_VIC_1920X1080P30,    0x01,0x1D,0x80,0x18,0x71,0x38,0x2D,0x40,0x58,0x2C,0x45,0x00,0xBA,0x88,0x21,0x00,0x00,0x1E}, //1080P30
    {HDMI_VIC_1920X1080P50,    0x02,0x3A,0x80,0xD0,0x72,0x38,0x2D,0x40,0x10,0x2C,0x45,0x80,0xBA,0x88,0x21,0x00,0x00,0x1E}, //1080P50
    {HDMI_VIC_1920X1080P60,    0x02,0x3A,0x80,0x18,0x71,0x38,0x2D,0x40,0x58,0x2C,0x45,0x00,0xBA,0x88,0x21,0x00,0x00,0x1E}, //1080P60
    {HDMI_VIC_3840X2160P30,    0x04,0x74,0x00,0x30,0xF2,0x70,0x5A,0x80,0xB0,0x58,0x8A,0x00,0x55,0x50,0x21,0x00,0x00,0x1E}, //4K30
    {HDMI_VIC_3840X2160P60,    0x08,0xE8,0x00,0x30,0xF2,0x70,0x5A,0x80,0xB0,0x58,0x8A,0x00,0x55,0x50,0x21,0x00,0x00,0x1E}, //4K60
    {HDMI_VIC_4096X2160P30,    0x04,0x74,0x00,0x30,0x01,0x70,0x5A,0x80,0x58,0x58,0x8A,0x00,0x55,0x50,0x21,0x00,0x00,0x1E}, //4096X2160P30
    {HDMI_VIC_4096X2160P60,    0x08,0xE8,0x00,0x30,0x01,0x70,0x5A,0x80,0x58,0x58,0x8A,0x00,0x55,0x50,0x21,0x00,0x00,0x1E}, //4096X2160P60

    {VESA_800X600P60,          0xA0,0x0F,0x20,0x00,0x31,0x58,0x1C,0x20,0x28,0x80,0x14,0x00,0x50,0x1D,0x74,0x00,0x00,0x1E}, //800X600P60
    {VESA_1024X768P60,         0x64,0x19,0x00,0x40,0x41,0x00,0x26,0x30,0x18,0x88,0x36,0x00,0x50,0x1D,0x74,0x00,0x00,0x1E}, //1024X768P60
    {VESA_1280X768P60,         0x0E,0x1F,0x00,0x80,0x51,0x00,0x1E,0x30,0x40,0x80,0x37,0x00,0x50,0x1D,0x74,0x00,0x00,0x1E}, //1280X768P60
    {VESA_1280X800P60,         0x9E,0x20,0x00,0x90,0x51,0x20,0x1F,0x30,0x48,0x80,0x36,0x00,0x50,0x1D,0x74,0x00,0x00,0x1E}, //1280X800P60
    {VESA_1280X960P60,         0x30,0x2A,0x00,0x08,0x52,0xC0,0x28,0x30,0x60,0x70,0x13,0x00,0x50,0x1D,0x74,0x00,0x00,0x1E}, //1280X960P60
    {VESA_1280X1024P60,        0x30,0x2A,0x00,0x98,0x51,0x00,0x2A,0x40,0x30,0x70,0x13,0x00,0x50,0x1D,0x74,0x00,0x00,0x1E}, //1280X1024P60
    {VESA_1360X768P60,         0x66,0x21,0x50,0xB0,0x51,0x00,0x1B,0x30,0x40,0x70,0x36,0x00,0x50,0x1D,0x74,0x00,0x00,0x1E}, //1360X768P60
    {VESA_1366X768P60,         0x66,0x21,0x56,0xAA,0x51,0x00,0x1E,0x30,0x46,0x8F,0x33,0x00,0x50,0x1D,0x74,0x00,0x00,0x1E}, //1366X768P60
    {VESA_1400X1050P60,        0x8F,0x2F,0x78,0xD0,0x51,0x1A,0x27,0x40,0x58,0x90,0x34,0x00,0x50,0x1D,0x74,0x00,0x00,0x1E}, //1400X1050P60
    {VESA_1440X900P60,         0x9A,0x29,0xA0,0xD0,0x51,0x84,0x22,0x30,0x50,0x98,0x36,0x00,0x50,0x1D,0x74,0x00,0x00,0x1E}, //1440X900P60
    {VESA_1600X900P60,         0x30,0x2A,0x40,0xC8,0x60,0x84,0x64,0x30,0x18,0x50,0x13,0x00,0x50,0x1D,0x74,0x00,0x00,0x1E}, //1600X900P60
    {VESA_1600X1200P60,        0x48,0x3F,0x40,0x30,0x62,0xB0,0x32,0x40,0x40,0xC0,0x13,0x00,0x50,0x1D,0x74,0x00,0x00,0x1E}, //1600X1200P60
    {VESA_1680X1050P60,        0x21,0x39,0x90,0x30,0x62,0x1A,0x27,0x40,0x68,0xB0,0x36,0x00,0x50,0x1D,0x74,0x00,0x00,0x1E}, //1680X1050P60
    {VESA_1920X1200P60,        0x7D,0x4B,0x80,0xA0,0x72,0xB0,0x2D,0x40,0x88,0xC8,0x36,0x00,0x50,0x1D,0x74,0x00,0x00,0x1E}, //1920X1200P60
    {VESA_2560X1600P60,        0x22,0x88,0x00,0xB0,0xA3,0x40,0x3A,0x60,0xC0,0x18,0x36,0x10,0x50,0x1D,0x74,0x00,0x00,0x1E}, //2560X1600P60
};

T_TimingMap aTimingTable[] =
{
    //VIC                       Name                   Hact  Vact  I/P Htotal Vtotal VFreq PClock
    { HDMI_VIC_1920X1080P24,    "1920x1080p@24",     { 1920, 1080, 0,  2750,  1125,  24,   74250,  }, },
    { HDMI_VIC_1920X1080P25,    "1920x1080p@25",     { 1920, 1080, 0,  2640,  1125,  25,   74250,  }, },
    { HDMI_VIC_1920X1080P30,    "1920x1080p@30",     { 1920, 1080, 0,  2200,  1125,  30,   74250,  }, },
    { HDMI_VIC_3840X2160P24,    "3840x2160p@24",     { 3840, 2160, 0,  5500,  2250,  24,   297000, }, },
    { HDMI_VIC_3840X2160P25,    "3840x2160p@25",     { 3840, 2160, 0,  5280,  2250,  25,   297000, }, },
    { HDMI_VIC_3840X2160P30,    "3840x2160p@30",     { 3840, 2160, 0,  4400,  2250,  30,   297000, }, },
    { HDMI_VIC_4096X2160P24,    "4096x2160p@24",     { 4096, 2160, 0,  5500,  2250,  24,   297000, }, },
    { HDMI_VIC_4096X2160P25,    "4096x2160p@25",     { 4096, 2160, 0,  5280,  2250,  25,   297000, }, },
    { HDMI_VIC_4096X2160P30,    "4096x2160p@30",     { 4096, 2160, 0,  4400,  2250,  30,   297000, }, },
    { HDMI_VIC_720X576P50_4_3,  "720x576p@50 4:3",   { 720,  576,  0,  864,   625,   50,   27000,  }, },
    { HDMI_VIC_720X576P50_16_9, "720x576p@50 16:9",  { 720,  576,  0,  864,   625,   50,   27000,  }, },
    { HDMI_VIC_1280X720P50,     "1280x720p@50",      { 1280, 720,  0,  1980,  750,   50,   74250,  }, },
    { HDMI_VIC_1920X1080I50,    "1920x1080i@50",     { 1920, 540,  1,  2640,  562,   50,   74250,  }, },
    { HDMI_VIC_720X576I50_4_3,  "720x576i@50 4:3",   { 720,  288,  1,  864,   312,   50,   27000,  }, },
    { HDMI_VIC_720X576I50_4_3,  "720x576i@50 4:3",   { 1440, 288,  1,  1728,  312,   50,   27000,  }, },
    { HDMI_VIC_720X576I50_16_9, "720x576i@50 16:9",  { 1440, 288,  1,  1728,  312,   50,   27000,  }, },
    { HDMI_VIC_1920X1080P50,    "1920x1080p@50",     { 1920, 1080, 0,  2640,  1125,  50,   148500, }, },
    { HDMI_VIC_3840X2160P50,    "3840x2160p@50",     { 3840, 2160, 0,  5280,  2250,  50,   594000, }, },
    { HDMI_VIC_4096X2160P50,    "4096x2160p@50",     { 4096, 2160, 0,  5280,  2250,  50,   594000, }, },
    { HDMI_VIC_640X480P60,      "640x480p@60",       { 640,  480,  0,  800,   525,   60,   25175,  }, },
    { HDMI_VIC_720X480P60_4_3,  "720x480p@60 4:3",   { 720,  480,  0,  858,   525,   60,   27000,  }, },
    { HDMI_VIC_720X480P60_16_9, "720x480p@60 16:9",  { 720,  480,  0,  858,   525,   60,   27000,  }, },
    { HDMI_VIC_1280X720P60,     "1280x720p@60",      { 1280, 720,  0,  1650,  750,   60,   74250,  }, },
    { HDMI_VIC_1920X1080I60,    "1920x1080i@60",     { 1920, 540,  1,  2200,  562,   60,   74250,  }, },
    { HDMI_VIC_720X480I60_4_3,  "720x480i@60 4:3",   { 720,  240,  1,  858,   262,   60,   27000,  }, },
    { HDMI_VIC_720X480I60_4_3,  "720x480i@60 4:3",   { 1440, 240,  1,  1716,  262,   60,   27000,  }, },
    { HDMI_VIC_720X480I60_16_9, "720x480i@60 16:9",  { 1440, 240,  1,  1716,  262,   60,   27000,  }, },
    { HDMI_VIC_1920X1080P60,    "1920x1080p@60",     { 1920, 1080, 0,  2200,  1125,  60,   148500, }, },
    { HDMI_VIC_3840X2160P60,    "3840x2160p@60",     { 3840, 2160, 0,  4400,  2250,  60,   594000, }, },
    { HDMI_VIC_4096X2160P60,    "4096x2160p@60",     { 4096, 2160, 0,  4400,  2250,  60,   594000, }, },

    //VESA                      Name                   Hact  Vact  I/P Htotal Vtotal VFreq PClock
    { VESA_800X600P60,          "800x600p@60",       { 800,  600,  0,  1056,  628,   60,   40000,  }, },
    { VESA_1024X768P60,         "1024x768p@60",      { 1024, 768,  0,  1344,  806,   60,   65000,  }, },
    { VESA_1280X768P60,         "1280x768p@60",      { 1280, 768,  0,  1644,  798,   60,   79500,  }, },
    { VESA_1280X800P60,         "1280x800p@60",      { 1280, 800,  0,  1680,  831,   60,   83500,  }, },
    { VESA_1280X960P60,         "1280x960p@60",      { 1280, 960,  0,  1800,  1000,  60,   108000, }, },
    { VESA_1280X1024P60,        "1280x1024p@60",     { 1280, 1024, 0,  1688,  1066,  60,   108000, }, },
    { VESA_1360X768P60,         "1360x768p@60",      { 1360, 768,  0,  1792,  795,   60,   85500,  }, },
    { VESA_1366X768P60,         "1366x768p@60",      { 1366, 768,  0,  1792,  798,   60,   85588,  }, },
    { VESA_1400X1050P60,        "1400x1050p@60",     { 1400, 1050, 0,  1864,  1089,  60,   121750, }, },
    { VESA_1440X900P60,         "1440x900p@60",      { 1440, 900,  0,  1904,  934,   60,   106500, }, },
    { VESA_1600X900P60,         "1600x900p@60",      { 1600, 900,  0,  1800,  1000,  60,   108000, }, },
    { VESA_1600X1200P60,        "1600x1200p@60",     { 1600, 1200, 0,  2160,  1250,  60,   162000, }, },
    { VESA_1680X1050P60,        "1680x1050p@60",     { 1680, 1050, 0,  2240,  1089,  60,   146250, }, },
    { VESA_1920X1200P60,        "1920x1200p@60",     { 1920, 1200, 0,  2592,  1245,  60,   193250, }, },
    { VESA_2560X1600P60,        "2560x1600p@60",     { 2560, 1600, 0,  3504,  1658,  60,   348500, }, },
};

void AddTiming(E_Timing i_eTiming)
{
    // 避免重复的push同一个timing
    vector<E_Timing>::iterator it = find(aSupportTimings.begin(), aSupportTimings.end(), i_eTiming);
    if(it == aSupportTimings.end())
    {
        aSupportTimings.push_back(i_eTiming);
    }
}

const char *ConvertTiming2Name(int i_nVic)
{
    int i = 0;
    for(i = 0; i < sizeof(aTimingTable)/sizeof(aTimingTable[0]); i++)
    {
        if(i_nVic == aTimingTable[i].s32Vic)
        {
            return aTimingTable[i].pName;
        }
    }
    return "None";
}

int DtdPrint(unsigned char *i_pDtd)
{
    int htotal = 0;
    int vtotal = 0;
    htotal = H_ACTIVE + H_BLANKING;
    vtotal = V_ACTIVE + V_BLANKING;

    printf("\tMode \t\"%dx%d\"", H_ACTIVE, V_ACTIVE );
    printf("\t# vfreq %3.3fHz, hfreq %6.3fkHz\n", (double)PIXEL_CLOCK/((double)vtotal*(double)htotal), (double)PIXEL_CLOCK/(double)(htotal*1000));

    printf("\t\t DotClock\t%f\n", (double)PIXEL_CLOCK/1000000.0);

    printf("\t\t HTimings\t%u %u %u %u\n", H_ACTIVE, H_FRONT_PORCH, H_SYNC_WIDTH, htotal);

    printf("\t\t VTimings\t%u %u %u %u\n", V_ACTIVE, V_FRONT_PORCH, V_SYNC_WIDTH, vtotal);

    if (INTERLACED || (SYNC_TYPE == SYNC_SEPARATE))
    {
        printf("\t\t Sync Profile\t%s\"%sHSync\" \"%sVSync\"\n", INTERLACED ? "\"Interlace\" ": "", HSYNC_POSITIVE ? "+": "-", VSYNC_POSITIVE ? "+": "-");
    }

    printf("\tEndMode\n");

    return 0;
}

int Dtd2Vic(unsigned char *i_pTable)
{
    int i = 0;
    int j = 0;
    int s32Vic = 0;
    unsigned char u8Valid = 0;

    for(i = 0; i < sizeof(aDtd18Byte)/sizeof(aDtd18Byte[0]); i++)
    {
        u8Valid = 0;
        if((i_pTable[0] == aDtd18Byte[i][1]) && (i_pTable[1] == aDtd18Byte[i][2])) // pixel clock
        {
            for(j = 2; j < 12; j++)
            {
                if(i_pTable[j] == aDtd18Byte[i][j+1])
                {
                    u8Valid += 1;
                }
            }
            if(u8Valid == 10) // 有12个字节相同则认为OK, 即只关注DTD的前12个字节
            {
                s32Vic = aDtd18Byte[i][0];
                break;
            }
        }
    }
    return s32Vic;
}

void DtdParse(unsigned char *i_pDtd)
{
    int i = 0;
    int s32Vic = 0;

    s32Vic = Dtd2Vic(i_pDtd);
    AddTiming((E_Timing)s32Vic);
    printf("\tDTD support timing: %s\n", ConvertTiming2Name(s32Vic));
}

void AudioParse(unsigned char *i_pTable, unsigned char i_u8Off)
{
    int i = 0;
    int j = 0;
    unsigned char u8Len = 0;

    printf("\nAudio Data Block\n");

    u8Len = i_pTable[i_u8Off] & 0x1F;
    tAudioData.u8Count = u8Len / 3;
    if(tAudioData.u8Count > 10)
    {
        tAudioData.u8Count = 10;
    }
    for(i = 0; i < tAudioData.u8Count; i++)
    {
        tAudioData.aSAD[i].eAudioFormat = (E_AudioFormat)((i_pTable[i_u8Off+1+3*i] >> 3) & 0x0F);
        tAudioData.aSAD[i].u8MaxChannels = (i_pTable[i_u8Off+1+3*i] & 0x07) + 1;
        tAudioData.aSAD[i].u8SampleRate = i_pTable[i_u8Off+1+3*i+1];
        tAudioData.aSAD[i].u8Byte3 = i_pTable[i_u8Off+1+3*i+2];

        printf("\tSAD%d support audio format: %s, max channels: %d\n",
            i+1, AUDIO_FORMAT(tAudioData.aSAD[i].eAudioFormat), tAudioData.aSAD[i].u8MaxChannels);
        printf("\tSAD%d support sample rate:", i+1);
        for(j = 0; j < 8; j++)
        {
            if(tAudioData.aSAD[i].u8SampleRate & (1<<j))
            {
                printf(" %s", SAMPLE_RATE(1<<j));
            }
        }
        printf("\n");
        printf("\tSAD%d byte3: 0x%02X\n", i+1, tAudioData.aSAD[i].u8Byte3);
    }
}

void VideoParse(unsigned char *i_pTable, unsigned char i_u8Off)
{
    int i = 0;
    unsigned char u8Len = 0;
    unsigned char u8Tmp;

    printf("\nVideo Data Block\n");

    u8Len = i_pTable[i_u8Off] & 0x1F;
    tVideoData.u8Count = u8Len;

    for(i = 0; i < u8Len; i++)
    {
        tVideoData.aVic[i] =  i_pTable[i_u8Off+1+i];
        u8Tmp = tVideoData.aVic[i];
        if(((u8Tmp >= 1)&&(u8Tmp <= 64)) || ((u8Tmp >= 129)&&(u8Tmp <= 192))) // remove native bit
        {
            u8Tmp &= 0x7F;
            tVideoData.aVic[i] = u8Tmp;
        }
        AddTiming((E_Timing)(tVideoData.aVic[i]));
        printf("\t%s\n", ConvertTiming2Name(tVideoData.aVic[i]));
    }
}

void Vsdb1Parse(unsigned char *i_pTable, unsigned char i_u8Off)
{
    int i = 0;
    unsigned char u8NextOffset = 0;
    unsigned char u83dOrderLen =0;
    unsigned char u8RemainingBytes = 0;
    unsigned char u82dVicOrder = 0;
    unsigned char u8Len = 0;
    unsigned char u83dStructure = 0;
    unsigned char u8Tmp = 0;
    unsigned short u16Tmp = 0;

    printf("\nH14b VSDB\n");

    u8Len = i_pTable[i_u8Off] & 0x1F;
    tVsdb1.u8PhyAddr0 = i_pTable[i_u8Off+4];
    tVsdb1.u8PhyAddr1 = i_pTable[i_u8Off+5];
    printf("\tCEC phyaddr: 0x%02x 0x%02x\n", tVsdb1.u8PhyAddr0, tVsdb1.u8PhyAddr1);

    if(u8Len > 5)
    {
        tVsdb1.u8DcSupport = i_pTable[i_u8Off+6];
        if(tVsdb1.u8DcSupport & 0x08)
        {
            printf("\tsupport deep color type:");
            if(tVsdb1.u8DcSupport & 0x10) printf(" %s", DEEP_COLOR(HDMI_DEEP_COLOR_10BIT));
            if(tVsdb1.u8DcSupport & 0x20) printf(" %s", DEEP_COLOR(HDMI_DEEP_COLOR_12BIT));
            if(tVsdb1.u8DcSupport & 0x40) printf(" %s", DEEP_COLOR(HDMI_DEEP_COLOR_16BIT));
        }
        printf("\n");
        if(u8Len == 6)
        {
            return;
        }

        tVsdb1.u32MaxTmdsClock = i_pTable[i_u8Off+7] * 5;
        printf("\tsupport max tmds clock: %dMHz\n", tVsdb1.u32MaxTmdsClock);
        if(u8Len == 7)
        {
            return;
        }

        tVsdb1.u8CnAndPresent = i_pTable[i_u8Off+8];
        if(tVsdb1.u8CnAndPresent & 0x80) // Latency_Fields_Present
        {
            tVsdb1.u8VideoLatency = i_pTable[i_u8Off+9];
            tVsdb1.u8AudioLatency = i_pTable[i_u8Off+10];
            u8NextOffset += 2;
            printf("\tVideo Latency: %dms\n", tVsdb1.u8VideoLatency);
            printf("\tAudio Latency: %dms\n", tVsdb1.u8AudioLatency);
        }
        if(tVsdb1.u8CnAndPresent & 0x40) // I_Latency_Fields_Present
        {
            tVsdb1.u8IVideoLatency = i_pTable[i_u8Off+11];
            tVsdb1.u8IAudioLatency = i_pTable[i_u8Off+12];
            u8NextOffset += 2;
            printf("\tI Video Latency: %dms\n", tVsdb1.u8IVideoLatency);
            printf("\tI Audio Latency: %dms\n", tVsdb1.u8IAudioLatency);
        }
        if(tVsdb1.u8CnAndPresent & 0x20) // HDMI_Video_present
        {
            tVsdb1.u8ImageSizeAnd3dPresent = i_pTable[i_u8Off+9+u8NextOffset];
            tVsdb1.u8ImageSizeFlag = (tVsdb1.u8ImageSizeAnd3dPresent & 0x18) >> 3;
            tVsdb1.u8HdmiVicLen = (i_pTable[i_u8Off+10+u8NextOffset] & 0xE0) >> 5;
            tVsdb1.u8Hdmi3dLen = i_pTable[i_u8Off+10+u8NextOffset] & 0x1F;

            printf("\tHDMI 4K VIC len: %d\n", tVsdb1.u8HdmiVicLen);
            for(i = 0; i < tVsdb1.u8HdmiVicLen; i++)
            {
                tVsdb1.u8Hdmi4kVic[i] = i_pTable[i_u8Off+11+u8NextOffset+i];
                if(tVsdb1.u8Hdmi4kVic[i] == HDMI_4K_VIC_3840X2160P30) AddTiming(HDMI_VIC_3840X2160P30);
                if(tVsdb1.u8Hdmi4kVic[i] == HDMI_4K_VIC_3840X2160P25) AddTiming(HDMI_VIC_3840X2160P25);
                if(tVsdb1.u8Hdmi4kVic[i] == HDMI_4K_VIC_3840X2160P24) AddTiming(HDMI_VIC_3840X2160P24);
                if(tVsdb1.u8Hdmi4kVic[i] == HDMI_4K_VIC_4096X2160P24) AddTiming(HDMI_VIC_4096X2160P24);
                printf("\t\t %s\n", HDMI_4K_VIC(tVsdb1.u8Hdmi4kVic[i]));
            }
            u8NextOffset += tVsdb1.u8HdmiVicLen;

            if(tVsdb1.u8Hdmi3dLen > 0)
            {
                tVsdb1.u8Support3D = 1;
                u8Tmp = tVsdb1.u8ImageSizeAnd3dPresent;
                if(((u8Tmp & 0x60) == 0x20) || ((u8Tmp & 0x60) == 0x40)) // 3D_Multi_present
                {
                    tVsdb1.u83dStructAll15_8 = i_pTable[i_u8Off+11+u8NextOffset];
                    tVsdb1.u83dStructAll7_0 = i_pTable[i_u8Off+11+u8NextOffset+1];
                    u16Tmp = (tVsdb1.u83dStructAll15_8 << 8) + tVsdb1.u83dStructAll7_0;
                    printf("\t3D support format:\n");
                    for(i = 0; i < 16; i++)
                    {
                        if(u16Tmp & (1<<i))
                        {
                            printf("\t\t %s\n", HDMI_3D_FORMAT(1<<i));
                        }
                    }
                    u8NextOffset += 2;
                }
                if((u8Tmp & 0x60) == 0x40) // 3D_Multi_present
                {
                    unsigned char u83dVicLen = 0;
                    u16Tmp = (i_pTable[i_u8Off+11+u8NextOffset] << 8) + i_pTable[i_u8Off+11+u8NextOffset+1];
                    printf("\t3D support VIC:\n");
                    for(i = 0; i < 16; i++)
                    {
                        if(u16Tmp & (1<<i))
                        {
                            tVsdb1.u83dVicSupport[u83dVicLen] = tVideoData.aVic[i];
                            printf("\t\t %d-%s\n", tVsdb1.u83dVicSupport[u83dVicLen], ConvertTiming2Name(tVsdb1.u83dVicSupport[u83dVicLen]));
                            u83dVicLen++;
                        }
                    }
                    tVsdb1.u83dVicSupportLen = u83dVicLen;
                    u8NextOffset += 2;
                }
                u8RemainingBytes = u8Len - 10 - u8NextOffset;
                for(i = 0; i < u8RemainingBytes; i++)
                {
                    u82dVicOrder = (i_pTable[i_u8Off+11+u8NextOffset+i] & 0xF0) >> 4;
                    u83dStructure = i_pTable[i_u8Off+11+u8NextOffset+i] & 0x0F;
                    tVsdb1.u163dOrder[u83dOrderLen] = (u83dStructure << 8) + tVideoData.aVic[u82dVicOrder];
                    printf("\t3D order: %04x\n", tVsdb1.u163dOrder[u83dOrderLen]);
                    if(u83dStructure == 0x08) i++;
                    u83dOrderLen++;
                }
                tVsdb1.u83dOrderLen = u83dOrderLen;
            }
        }
    }
}

void Vsdb2Parse(unsigned char *i_pTable, unsigned char i_u8Off)
{
    unsigned char u8Tmp;

    printf("\nHF-VSDB\n");

    tVsdb2.u32MaxTmdsClock = i_pTable[i_u8Off+5] * 5;
    printf("\tsupport max tmds clock: %dMHz\n", tVsdb2.u32MaxTmdsClock);

    u8Tmp = i_pTable[i_u8Off+6];
    tVsdb2.u8ScdcPresent = (u8Tmp & 0x80) >> 7;
    tVsdb2.u8RrCapable = (u8Tmp & 0x40) >> 6;
    tVsdb2.u8Lte340mScramble = (u8Tmp & 0x08) >> 3;
    tVsdb2.u8IndependentView = (u8Tmp & 0x04) >> 2;
    tVsdb2.u8DualView = (u8Tmp & 0x02) >> 1;
    tVsdb2.u83dOsd = u8Tmp & 0x01;

    u8Tmp = i_pTable[i_u8Off+7];
    tVsdb2.u8Dc16Bit420 = (u8Tmp & 0x04) >> 2;
    tVsdb2.u8Dc12Bit420 = (u8Tmp & 0x02) >> 1;
    tVsdb2.u8Dc10Bit420 = u8Tmp & 0x01;
    if(tVsdb2.u8Dc16Bit420) printf("\tsupport DC_48bit_420\n");
    if(tVsdb2.u8Dc12Bit420) printf("\tsupport DC_36bit_420\n");
    if(tVsdb2.u8Dc10Bit420) printf("\tsupport DC_30bit_420\n");
}

void ExtTagParse(unsigned char *i_pTable, unsigned char i_u8Off)
{
    int i = 0;
    int j = 0;
    unsigned char u8Tag = 0;
    unsigned char u8Len = 0;
    unsigned char u8Tmp = 0;
    unsigned char u8Vic = 0;

    u8Tag = i_pTable[i_u8Off+1];
    u8Len = i_pTable[i_u8Off] & 0x1F;

    if(u8Tag == CEA_EXT_TAG_CDB) // Colorimetry Data Block
    {
        printf("\nColorimetry Data Block\n");

        u8Tmp = i_pTable[i_u8Off+2];
        printf("\tsupport colorimetry:\n");
        for(i = 0; i < 8; i++)
        {
            if(u8Tmp & (1<<i))
            {
                printf("\t\t %s\n", HDMI_COLORIMETRY(1<<i));
            }
        }

        u8Tmp = i_pTable[i_u8Off+3];
        printf("\tsupport metadata profiles:\n");
        if(u8Tmp & 0x01) printf("\t\t %s\n", "Metadata Profile 0");
        if(u8Tmp & 0x02) printf("\t\t %s\n", "Metadata Profile 1");
        if(u8Tmp & 0x04) printf("\t\t %s\n", "Metadata Profile 2");
        if(u8Tmp & 0x08) printf("\t\t %s\n", "Metadata Profile 3");
    }
    else if(u8Tag == CEA_EXT_TAG_HDR) // HDR
    {
        printf("\nHDR Static Metadata Data Block\n");

        // support HDR
        aHdrContent[0] = i_pTable[i_u8Off+2];
        aHdrContent[1] = i_pTable[i_u8Off+3];

        printf("\tsupport EOTF:\n");
        if(aHdrContent[0] & 0x01) printf("\t\t %s\n", "Traditional SDR");
        if(aHdrContent[0] & 0x02) printf("\t\t %s\n", "Traditional HDR");
        if(aHdrContent[0] & 0x04) printf("\t\t %s\n", "SMPTE ST 2084 [2]");
        if(aHdrContent[0] & 0x08) printf("\t\t %s\n", "Hybrid Log-Gamma(HLG)");

        printf("\tsupport static metadata descriptor:\n");
        if(aHdrContent[1] & 0x01) printf("\t\t %s\n", "Type 1");
    }
    else if(u8Tag == CEA_EXT_TAG_Y420VDB) // only support 420
    {
        printf("\nYCbCr 4:2:0 Video Data Block\n");
        printf("\tonly support YCbCr 4:2:0 VICs:\n");
        for(i = 0; i < u8Len-1; i++)
        {
            printf("\t\t %s\n", ConvertTiming2Name(i_pTable[i_u8Off+2+i]));
        }
    }
    else if(u8Tag == CEA_EXT_TAG_Y420CMDB) // support 420
    {
        printf("\nYCbCr 4:2:0 Capability Map Data Block\n");
        printf("\tsupport YCbCr 4:2:0 VICs:\n");
        for(i = 0; i < u8Len-1; i++)
        {
            u8Tmp = i_pTable[i_u8Off+2+i]; // bitmap table
            if(u8Tmp)
            {
                for(j = 0; j < 8; j++)
                {
                    if(u8Tmp & (1<<j)) // bitmap compare
                    {
                        u8Vic = tVideoData.aVic[i*8+j]; // real vic
                        printf("\t\t %s\n", ConvertTiming2Name(u8Vic));
                    }
                }
            }
        }
    }
}

int ParseHdmiEdidBlock0(unsigned char *i_pEdid)
{
    int i = 0;
    int j = 0;
    unsigned char *block;
    unsigned char DisplayDescriptorFlag[2] = {0x00, 0x00};
    unsigned char ManufacturerName[3] = {0};
    unsigned short ProductCode;
    unsigned int SerialNumber;
    unsigned char WeekManufacturer;
    unsigned int YearManufacturer;
    unsigned char ProductName[13] = {0};
    unsigned short Sum = 0;
    unsigned char Checksum = 0;
    int DetailTimingBlockType = UNKNOW_DESCRIPTOR;

    printf("\nVendor and Product Information\n");
    ManufacturerName[0] = (i_pEdid[0x08]>>2)+'A'-1;
    ManufacturerName[1] = (((i_pEdid[0x08]<<3) | (i_pEdid[0x09]>>5)) & 0x1f)+'A'-1;
    ManufacturerName[2] = (i_pEdid[0x09] & 0x1f)+'A'-1;
    printf("\tManufacturer Name: %c%c%c\n", ManufacturerName[0], ManufacturerName[1], ManufacturerName[2]);
    ProductCode = i_pEdid[0x0B]<<8|i_pEdid[0x0A];
    printf("\tProduct Code: %04X\n", ProductCode);
    SerialNumber = i_pEdid[0x0F]<<24|i_pEdid[0x0E]<<16|i_pEdid[0x0D]<<8|i_pEdid[0x0C];
    printf("\tSerial Number: %08X\n", SerialNumber);
    WeekManufacturer = i_pEdid[0x10];
    printf("\tWeek of Manufacture: %d\n", WeekManufacturer);
    YearManufacturer = (i_pEdid[0x11]+1990);
    printf("\tYear of Manufacture: %d\n", YearManufacturer);

    printf("\nEDID Structure\n");
    printf("\tVersion no.: %d\n", i_pEdid[0x12]);
    printf("\tRevision no.: %d\n", i_pEdid[0x13]);

    printf("\nBasic Display Parameters and Features\n");
    printf("\tVideo Input Signal Type: %s\n", (i_pEdid[0x14]>>7) ? "Digital": "Analog");
    if(i_pEdid[0x14]>>7)
    {
        // Digital
        printf("\tInterface signal compatible with VESA DFP 1.X: %s\n", (i_pEdid[0x14]&0x01) ? "Compatible": "Not Compatible");
    }
    printf("\tMax Horz Size (in cm): %d\n", i_pEdid[0x15]);
    printf("\tMax Vert Size (in cm): %d\n", i_pEdid[0x16]);
    if(i_pEdid[0x17] == 0xFF)
    {
        printf("\tGamma Value: Not defined\n");
    }
    else
    {
        printf("\tGamma Value: %d.%d\n", (i_pEdid[0x17]+100)/100, (i_pEdid[0x17]+100)%100);
    }
    printf("\tFeature Support (DPMS)\n");
    printf("\t\t Standby Mode: %s\n", (i_pEdid[0x18]&0x80) ? "Supported": "Not Supported");
    printf("\t\t Suspend Mode: %s\n", (i_pEdid[0x18]&0x40) ? "Supported": "Not Supported");
    printf("\t\t Active Off Mode: %s\n", (i_pEdid[0x18]&0x20) ? "Supported": "Not Supported");
    printf("\t\t Display Type: ");
    switch((i_pEdid[0x18]&0x18)>>3)
    {
        case 0: printf( "Monochrome display\n");         break;
        case 1: printf( "RGB color display\n");          break;
        case 2: printf( "Non-RGB multicolor display\n"); break;
        case 3: printf( "Undefined display\n");          break;
    }
    printf("\t\t Color Space: %s\n", (i_pEdid[0x18]&0x04) ? "sRGB": "Alternate");
    printf("\t\t Preferred Timing: %s\n", (i_pEdid[0x18]&0x02) ? "1st DTD": "Non indicated");
    printf("\t\t GTF Timing: %s\n", (i_pEdid[0x18]&0x01) ? "Supported": "Not Supported");

    printf("\nColor Characteristic\n");
    printf("\tRed_x: 0.%.3d\n", ((i_pEdid[0x1B]<<2)  | ((i_pEdid[0x19]>>6)&0x03))*1000/1024);
    printf("\tRed_y: 0.%.3d\n", ((i_pEdid[0x1C]<<2)  | ((i_pEdid[0x19]>>4)&0x03))*1000/1024);
    printf("\tGreen_x: 0.%.3d\n", ((i_pEdid[0x1D]<<2)  | ((i_pEdid[0x19]>>2)&0x03))*1000/1024);
    printf("\tGreen_y: 0.%.3d\n", ((i_pEdid[0x1E]<<2) | (i_pEdid[0x19]&0x03))*1000/1024);
    printf("\tBlue_x: 0.%.3d\n", ((i_pEdid[0x1F]<<2)  | ((i_pEdid[0x1A]>>6)&0x03))*1000/1024);
    printf("\tBlue_y: 0.%.3d\n", ((i_pEdid[0x20]<<2)  | ((i_pEdid[0x1A]>>4)&0x03))*1000/1024);
    printf("\tWhite_x: 0.%.3d\n", ((i_pEdid[0x21]<<2)  | ((i_pEdid[0x1A]>>2)&0x03))*1000/1024);
    printf("\tWhite_y: 0.%.3d\n", ((i_pEdid[0x22]<<2)  | (i_pEdid[0x1A]&0x03))*1000/1024);

    printf("\nEstablished Timings\n");
    printf("\tEstablished Timings I \n");
    if(i_pEdid[0x23]&0x80)    printf("\t\t 720 x 400 @ 70Hz IBM, VGA\n");
    if(i_pEdid[0x23]&0x40)    printf("\t\t 720 x 400 @ 88Hz IBM, XGA2\n");
    if(i_pEdid[0x23]&0x20)    { printf("\t\t 640 x 480 @ 60Hz IBM, VGA\n"); AddTiming(HDMI_VIC_640X480P60); }
    if(i_pEdid[0x23]&0x10)    printf("\t\t 640 x 480 @ 67Hz Apple, Mac II\n");
    if(i_pEdid[0x23]&0x08)    printf("\t\t 640 x 480 @ 72Hz VESA\n");
    if(i_pEdid[0x23]&0x04)    printf("\t\t 640 x 480 @ 75Hz VESA\n");
    if(i_pEdid[0x23]&0x02)    printf("\t\t 800 x 600 @ 56Hz VESA\n");
    if(i_pEdid[0x23]&0x01)    { printf("\t\t 800 x 600 @ 60Hz VESA\n"); AddTiming(VESA_800X600P60); }
    if(i_pEdid[0x23]== 0x00)  printf("\t\t None\n");
    printf("\tEstablished Timings II \n");
    if(i_pEdid[0x24]&0x80)    printf("\t\t 800 x 600 @ 72Hz VESA\n");
    if(i_pEdid[0x24]&0x40)    printf("\t\t 800 x 600 @ 75Hz VESA\n");
    if(i_pEdid[0x24]&0x20)    printf("\t\t 832 x 624 @ 75Hz Apple, Mac II\n");
    if(i_pEdid[0x24]&0x10)    printf("\t\t 1024 x 768 @ 87Hz IBM\n");
    if(i_pEdid[0x24]&0x08)    { printf("\t\t 1024 x 768 @ 60Hz VESA\n"); AddTiming(VESA_1024X768P60); }
    if(i_pEdid[0x24]&0x04)    printf("\t\t 1024 x 768 @ 70Hz VESA\n");
    if(i_pEdid[0x24]&0x02)    printf("\t\t 1024 x 768 @ 75Hz VESA\n");
    if(i_pEdid[0x24]&0x01)    printf("\t\t 1280 x 1024 @ 75Hz VESA\n");
    if(i_pEdid[0x24]== 0x00)  printf("\t\t None\n");
    printf("\tManufacturer's Timings\n");
    if(i_pEdid[0x25]&0x80)    printf("\t\t 1152 x 870 @ 75Hz Apple, Mac II\n");
    else                   printf("\t\t None\n");

    printf("\nStandard Timings\n");
    for(i = 0; i < 8; i++)
    {
        printf("\tStandard Timing %d\n", i+1);
        if((i_pEdid[0x26+i*2] == 0x01) && (i_pEdid[0x26+i*2+1] == 0x01))
        {
            printf("\t\t Unused\n");
        }
        else
        {
            unsigned int HActive = (i_pEdid[0x26+i*2]+31)*8;
            unsigned int VActive = 0;
            unsigned char u8Rate = 0;
            printf("\t\t Horizontal active pixels: %d\n", HActive);
            printf("\t\t Image Aspect ratio: ");
            switch((i_pEdid[0x26+i*2+1]&0xC0)>>6)
            {
                case 0: printf("16:10\n"); VActive = HActive * 10 / 16; break;
                case 1: printf("4:3\n");   VActive = HActive * 3 / 4;   break;
                case 2: printf("5:4\n");   VActive = HActive * 4 / 5;   break;
                case 3: printf("16:9\n");  VActive = HActive * 9 / 16;  break;
            }
            u8Rate = (i_pEdid[0x26+i*2+1]&0x3F)+60;
            printf("\t\t Refresh Rate: %d Hz\n", u8Rate);

            if(u8Rate == 60) // only care 60Hz
            {
                int j = 0;
                for(j = 0; j < sizeof(aTimingTable)/sizeof(aTimingTable[0]); j++)
                {
                    if((HActive == aTimingTable[j].tTimingInfo.u32HActive)
                        && (VActive == aTimingTable[j].tTimingInfo.u32VActive)
                        && (u8Rate == aTimingTable[j].tTimingInfo.u32VFreq))
                    {
                        AddTiming((E_Timing)(aTimingTable[j].s32Vic));
                        break;
                    }
                }
            }
        }
    }

    block = i_pEdid + BLOCK0_DTD_START;

    for( i = 0; i < BLOCK0_TOTAL_DTD; i++, block += DTD_SIZE)
    {
        if(memcmp(DisplayDescriptorFlag, block, 2) == 0)
        {
            if(block[2] != 0)
                DetailTimingBlockType = UNKNOW_DESCRIPTOR;
            else
                DetailTimingBlockType = block[3];
        }
        else
        {
            DetailTimingBlockType = DETAILED_TIMING_DEFINITION;
        }


        printf("\nBlock0 Detailed Timing Descriptor %d\n", i+1);
        switch(DetailTimingBlockType)
        {
            case DETAILED_TIMING_DEFINITION:
                DtdParse(block);
                DtdPrint(block);
                break;
            case MONITOR_NAME:
                for(j = 5; j < DTD_SIZE; j++)
                {
                    ProductName[j-5] = block[j];
                    if(block[j] == 0x0A) // end string
                    {
                        ProductName[j-5] = 0x00;
                        break;
                    }
                }
                printf("\tMonitor name: %s\n", ProductName);
                break;
            case RANGE_LIMITS:
                printf("\tMin. Vertical rate (Hz): %d\n", block[5]);
                printf("\tMax. Vertical rate (Hz): %d\n", block[6]);
                printf("\tMin. Horizontal rate (KHz): %d\n", block[7]);
                printf("\tMax. Horizontal rate (KHz): %d\n", block[8]);
                printf("\tMax. Supported Pixel Clock rate (KHz): %d\n", block[9]*10);
                if(block[10] == 0x00)
                {
                    printf("\tDefault GTF supported\n");
                }
                else if(block[10] == 0x02)
                {
                    printf("\tSecondary GTF supported\n");
                }
                break;
            case PRODUCT_SERIAL_NUMBER:
                printf("\tProduct Serial Number: ");
                for(int k = 0; k < 13; k++)
                {
                    printf("%c", block[k+5]);
                    if(block[k+5] == 0x0A) break;
                }
                break;         
            default:
                break;
        }
    }

    printf("\nExtension Flag\n");
    printf("\tExtension Flag: %d\n", i_pEdid[0x7E]);

    for( i = 0; i < EDID_LENGTH-1; i++)
    {
        Sum += i_pEdid[i];
    }
    Checksum = 0x100 - (Sum & 0xFF);
    printf("\nChecksum\n");
    printf("\tEDID Block0 checksum: %X\n", Checksum);

    return 1;
}

unsigned char ParseHdmiEdidBlock1(unsigned char *i_pEdid)
{
    int i = 0;
    int j = 0;
    unsigned char u8Offset = 0;
    unsigned char u8Len = 0;
    unsigned char u8CeaType = 0;
    unsigned char aDtd[18] = {0};
    unsigned char u8DtdOffset = 0;
    unsigned char u8Tmp = 0;
    unsigned char u8SpeakerInfo = 0;

    u8DtdOffset = i_pEdid[2];
    u8Offset = 4;
    u8Len = (i_pEdid[4] & 0x1F);
    for(;;)
    {
        u8CeaType = (i_pEdid[u8Offset] & 0xE0) >> 5;
        switch(u8CeaType)
        {
            case CEA_TAG_ADB:
                AudioParse(i_pEdid, u8Offset);
                break;
            case CEA_TAG_VDB:
                VideoParse(i_pEdid, u8Offset);
                break;
            case CEA_TAG_VSDB:
                if((i_pEdid[u8Offset+1] == 0x03) && (i_pEdid[u8Offset+2] == 0x0C) && (i_pEdid[u8Offset+3] == 0x00))
                {
                    Vsdb1Parse(i_pEdid, u8Offset);
                }
                else if((i_pEdid[u8Offset+1] == 0xD8) && (i_pEdid[u8Offset+2] == 0x5D) && (i_pEdid[u8Offset+3] == 0xC4))
                {
                    Vsdb2Parse(i_pEdid, u8Offset);
                }
                break;
            case CEA_TAG_SPK:
                u8SpeakerInfo = i_pEdid[u8Offset+1];
                printf("\nSpeaker Allocation Data Block\n");
                printf("\tspeaker info: 0x%02X\n", u8SpeakerInfo);
                break;
            case CEA_TAG_EXT:
                ExtTagParse(i_pEdid, u8Offset);
                break;
            default:
                break;
        }
        u8Offset += (u8Len + 1);
        u8Len = (i_pEdid[u8Offset] & 0x1F);
        if(u8Offset >= u8DtdOffset)
        {
            break;
        }
    }

    u8Tmp = EDID_LENGTH - u8DtdOffset;
    u8Tmp = u8Tmp/DTD_SIZE;
    for(i = 0; i < u8Tmp; i++)
    {
        printf("\nBlock1 Detailed Timing Descriptor %d\n", i+1);
        for(j = 0; j < DTD_SIZE; j++)
        {
            aDtd[j] = i_pEdid[u8DtdOffset+j+i*DTD_SIZE];
        }
        DtdParse(aDtd);
        DtdPrint(aDtd);
    }

    return 1;
}

int main(int argc, char *argv[])
{
    int i = 0;
    ParseHdmiEdidBlock0(aTestEdid);
    ParseHdmiEdidBlock1(aTestEdid+EDID_LENGTH);

    // 存放分辨率的地方共有5处: Established Timing, Standard Timing, DTD, VDB, H14b VSDB
    // 列出所支持的分辨率, 24Hz/25Hz/30Hz/50Hz/60Hz都会列出来, 其它Hz的不要
    printf("\nTotal support %ld timings:\n", aSupportTimings.size());
    for(i = 0; i < aSupportTimings.size(); i++)
    {
        printf("\t%s\n", ConvertTiming2Name(aSupportTimings[i]));
    }

    return 0;
}

三星电视的EDID运行结果如下

Vendor and Product Information
	Manufacturer Name: SAM
	Product Code: 0D3B
	Serial Number: 01000600
	Week of Manufacture: 1
	Year of Manufacture: 2016

EDID Structure
	Version no.: 1
	Revision no.: 3

Basic Display Parameters and Features
	Video Input Signal Type: Digital
	Interface signal compatible with VESA DFP 1.X: Not Compatible
	Max Horz Size (in cm): 89
	Max Vert Size (in cm): 50
	Gamma Value: 2.20
	Feature Support (DPMS)
		 Standby Mode: Not Supported
		 Suspend Mode: Not Supported
		 Active Off Mode: Not Supported
		 Display Type: RGB color display
		 Color Space: Alternate
		 Preferred Timing: 1st DTD
		 GTF Timing: Not Supported

Color Characteristic
	Red_x: 0.640
	Red_y: 0.330
	Green_x: 0.300
	Green_y: 0.600
	Blue_x: 0.150
	Blue_y: 0.060
	White_x: 0.280
	White_y: 0.290

Established Timings
	Established Timings I 
		 720 x 400 @ 70Hz IBM, VGA
		 640 x 480 @ 60Hz IBM, VGA
		 640 x 480 @ 67Hz Apple, Mac II
		 640 x 480 @ 72Hz VESA
		 640 x 480 @ 75Hz VESA
		 800 x 600 @ 60Hz VESA
	Established Timings II 
		 800 x 600 @ 72Hz VESA
		 800 x 600 @ 75Hz VESA
		 832 x 624 @ 75Hz Apple, Mac II
		 1024 x 768 @ 60Hz VESA
		 1024 x 768 @ 70Hz VESA
		 1024 x 768 @ 75Hz VESA
		 1280 x 1024 @ 75Hz VESA
	Manufacturer's Timings
		 1152 x 870 @ 75Hz Apple, Mac II

Standard Timings
	Standard Timing 1
		 Horizontal active pixels: 1152
		 Image Aspect ratio: 4:3
		 Refresh Rate: 75 Hz
	Standard Timing 2
		 Horizontal active pixels: 1280
		 Image Aspect ratio: 16:9
		 Refresh Rate: 60 Hz
	Standard Timing 3
		 Horizontal active pixels: 1280
		 Image Aspect ratio: 16:10
		 Refresh Rate: 60 Hz
	Standard Timing 4
		 Horizontal active pixels: 1280
		 Image Aspect ratio: 5:4
		 Refresh Rate: 60 Hz
	Standard Timing 5
		 Horizontal active pixels: 1440
		 Image Aspect ratio: 16:10
		 Refresh Rate: 60 Hz
	Standard Timing 6
		 Horizontal active pixels: 1600
		 Image Aspect ratio: 16:9
		 Refresh Rate: 60 Hz
	Standard Timing 7
		 Horizontal active pixels: 1680
		 Image Aspect ratio: 16:10
		 Refresh Rate: 60 Hz
	Standard Timing 8
		 Unused

Block0 Detailed Timing Descriptor 1
	DTD support timing: 3840x2160p@60
	Mode 	"3840x2160"	# vfreq 60.000Hz, hfreq 135.000kHz
		 DotClock	594.000000
		 HTimings	3840 176 88 4400
		 VTimings	2160 8 10 2250
		 Sync Profile	"+HSync" "+VSync"
	EndMode

Block0 Detailed Timing Descriptor 2
	DTD support timing: 1920x1080p@60
	Mode 	"1920x1080"	# vfreq 60.000Hz, hfreq 67.500kHz
		 DotClock	148.500000
		 HTimings	1920 88 44 2200
		 VTimings	1080 4 5 1125
		 Sync Profile	"+HSync" "+VSync"
	EndMode

Block0 Detailed Timing Descriptor 3
	Min. Vertical rate (Hz): 24
	Max. Vertical rate (Hz): 75
	Min. Horizontal rate (KHz): 15
	Max. Horizontal rate (KHz): 135
	Max. Supported Pixel Clock rate (KHz): 600
	Default GTF supported

Block0 Detailed Timing Descriptor 4
	Monitor name: SAMSUNG

Extension Flag
	Extension Flag: 1

Checksum
	EDID Block0 checksum: 5C

Video Data Block
	3840x2160p@60
	1920x1080p@60
	1920x1080p@50
	1280x720p@60
	1280x720p@50
	1920x1080i@60
	1920x1080i@50
	1920x1080p@24
	1920x1080p@25
	1920x1080p@30
	3840x2160p@24
	3840x2160p@25
	3840x2160p@30
	3840x2160p@50
	4096x2160p@50
	4096x2160p@60
	4096x2160p@24
	4096x2160p@25
	4096x2160p@30
	720x480i@60 16:9
	720x576i@50 16:9
	720x480p@60 16:9
	720x576p@50 16:9

Audio Data Block
	SAD1 support audio format: PCM, max channels: 2
	SAD1 support sample rate: 32K 44.1K 48K
	SAD1 byte3: 0x07
	SAD2 support audio format: AC3, max channels: 6
	SAD2 support sample rate: 32K 44.1K 48K
	SAD2 byte3: 0x50
	SAD3 support audio format: DTS, max channels: 6
	SAD3 support sample rate: 48K
	SAD3 byte3: 0xC0

Speaker Allocation Data Block
	speaker info: 0x01

Colorimetry Data Block
	support colorimetry:
		 XVYCC-601
		 XVYCC-709
		 BT.2020-YCC
		 BT.2020-RGB
	support metadata profiles:
		 Metadata Profile 0

H14b VSDB
	CEC phyaddr: 0x10 0x00
	support deep color type: 10BIT 12BIT
	support max tmds clock: 300MHz
	HDMI 4K VIC len: 4
		 3840x2160p@30
		 3840x2160p@25
		 3840x2160p@24
		 4096x2160p@24

HF-VSDB
	support max tmds clock: 600MHz
	support DC_36bit_420
	support DC_30bit_420

HDR Static Metadata Data Block
	support EOTF:
		 Traditional SDR
		 SMPTE ST 2084 [2]
	support static metadata descriptor:
		 Type 1

YCbCr 4:2:0 Capability Map Data Block
	support YCbCr 4:2:0 VICs:
		 3840x2160p@60
		 3840x2160p@50
		 4096x2160p@50
		 4096x2160p@60

Block1 Detailed Timing Descriptor 1
	DTD support timing: 1920x1080i@50
	Mode 	"1920x540"	# vfreq 50.044Hz, hfreq 28.125kHz
		 DotClock	74.250000
		 HTimings	1920 48 44 2640
		 VTimings	540 2 5 562
		 Sync Profile	"Interlace" "+HSync" "+VSync"
	EndMode

Block1 Detailed Timing Descriptor 2
	DTD support timing: 1366x768p@60
	Mode 	"1366x768"	# vfreq 59.790Hz, hfreq 47.712kHz
		 DotClock	85.500000
		 HTimings	1366 70 143 1792
		 VTimings	768 3 3 798
		 Sync Profile	"+HSync" "+VSync"
	EndMode

Total support 32 timings:
	640x480p@60
	800x600p@60
	1024x768p@60
	1280x720p@60
	1280x800p@60
	1280x1024p@60
	1440x900p@60
	1600x900p@60
	1680x1050p@60
	3840x2160p@60
	1920x1080p@60
	1920x1080p@50
	1280x720p@50
	1920x1080i@60
	1920x1080i@50
	1920x1080p@24
	1920x1080p@25
	1920x1080p@30
	3840x2160p@24
	3840x2160p@25
	3840x2160p@30
	3840x2160p@50
	4096x2160p@50
	4096x2160p@60
	4096x2160p@24
	4096x2160p@25
	4096x2160p@30
	720x480i@60 16:9
	720x576i@50 16:9
	720x480p@60 16:9
	720x576p@50 16:9
	1366x768p@60

你可能感兴趣的:(嵌入式)