diff options
Diffstat (limited to 'deps')
-rw-r--r-- | deps/sysobj_early/data/edid.ids | 1 | ||||
-rw-r--r-- | deps/sysobj_early/data/vendor.ids | 189 | ||||
-rw-r--r-- | deps/sysobj_early/include/util_edid.h | 56 | ||||
-rw-r--r-- | deps/sysobj_early/src/util_edid.c | 379 |
4 files changed, 518 insertions, 107 deletions
diff --git a/deps/sysobj_early/data/edid.ids b/deps/sysobj_early/data/edid.ids index 575287b6..9f959804 100644 --- a/deps/sysobj_early/data/edid.ids +++ b/deps/sysobj_early/data/edid.ids @@ -28,6 +28,7 @@ BNQ BenQ BOE BOE CMN Chimei Innolux Corporation CMO Chi Mei Optoelectronics +CNL Valve Corporation CRO Extraordinary Technologies CUK Calibre UK DEL Dell diff --git a/deps/sysobj_early/data/vendor.ids b/deps/sysobj_early/data/vendor.ids index 8c7d8b6f..84524b3a 100644 --- a/deps/sysobj_early/data/vendor.ids +++ b/deps/sysobj_early/data/vendor.ids @@ -128,13 +128,89 @@ name Toshiba Corporation name Vizio name_short VIZIO ansi_color 0;30;107 + match_string Vizio note EDID vendor: VIZ match_string_exact VIZ +name AOC International + name_short AOC + url www.aoc.com + wikipedia AOC International + ansi_color 0;97;44 + match_string_case AOC + note formerly Admiral Overseas Corporation + match_string Admiral Overseas Corporation + match_string Admiral + +name Magewell + url www.magewell.com + ansi_color 0;34;107 + match_string Magewell + +name Harman International + name_short Harman + url www.harman.com + ansi_color 0;34;107 + match_string Harman International + match_string Harman + +name Oculus VR + name_short Oculus + url www.oculus.com + ansi_color 0;97;100 + wikipedia Oculus VR + match_string Oculus VR + match_string Oculus + +name Yamaha Corporation + name_short Yamaha + url www.yamaha.com + wikipedia Yamaha Corporation + ansi_color 0;35;107 + match_string Yamaha + +name AU Optronics Corporation + name_short AUO + url www.auo.com + wikipedia AU Optronics + ansi_color 0;34;107 + match_string AU Optronics + match_string_case AUO + +name Planar + name_short PLANAR + url www.planar.com + ansi_color 0;91;40 + match_string Planar + +name Seiko Epson Corporation + name_short EPSON + url epson.com + wikipedia Seiko Epson + ansi_color 0;34;107 + match_string Seiko Epson + match_string Epson + match_string Seiko + +# Company defunct, now brand name of Chinese company +name Eastman Kodak Company + name_short Kodak + wikipedia Kodak + ansi_color 0;31;43 + match_string Kodak + +# Company defunct, now brand name of Chinese company +name Westinghouse Electronics + name_short W + wikipedia Westinghouse Electronics + ansi_color 0;97;44 + match_string Westinghouse + name ViewSonic Corporation name_short ViewSonic url www.viewsonic.com ansi_color 0;35;103 + match_string ViewSonic note EDID vendor: VSC match_string_exact VSC @@ -164,17 +240,14 @@ name Plextor url www.plextor.be match_string Plextor -name Western Digital - name_short WD - url www.wdc.com - ansi_color 0;37;40 - match_string_case WDC - name LG Electronics name_short LG url www.lge.com ansi_color 0;97;41 + match_string LG Electronics [Lucky Goldstar Co. Ltd] + match_string Lucky Goldstar match_string Lucky-Goldstar + match_string LG Semi match_string_case LG name LG Electronics (formerly Goldstar) @@ -269,9 +342,12 @@ name Qualcomm (formerly Atheros) match_string Atheros name Panasonic Industry Company +# AKA: Matsushita Electric Industrial name_short Panasonic url www.panasonic.com ansi_color 0;30;107 + match_string Panasonic + match_string Matsushita match_string MATSHITA note EDID vendor: MEI match_string_exact MEI @@ -299,6 +375,7 @@ name International Business Machines Corporation name_short IBM url www.ibm.com ansi_color 0;94;107 + match_string International Business Machines match_string_case IBM name Dell Computer @@ -322,6 +399,8 @@ name Fujitsu url www.fujitsu.com ansi_color 0;31;107 match_string FUJITSU + name_short Fujitsu/Siemens + match_string Fujitsu Siemens name Sony name_short SONY @@ -332,6 +411,14 @@ name Sony note EDID vendor: SNY match_string_exact SNY +name Sony Mobile + name_short SONY + url www.sony.com + ansi_color 0;30;107 + match_string Sony Mobile + name_short SONY/Ericsson + match_string Sony Ericsson + name SanDisk url www.sandisk.com ansi_color 0;31;40 @@ -467,6 +554,13 @@ name BenQ ansi_color 0;35;107 match_string BENQ +name BenQ (formerly Acer Peripherals) + name_short BenQ/acer + url www.benq.com + ansi_color 0;35;107 + match_string Acer Peripherals + match_string Acer Peripherals Inc. (now BenQ Corp.) + name Holtek Semiconductor name_short Holtek url www.holtek.com @@ -608,6 +702,7 @@ name Crucial (Micron) url www.crucial.com ansi_color 0;37;44 match_string Crucial + match_string Micron/Crucial name Toshiba Samsung Storage Technology name_short TSST @@ -622,7 +717,7 @@ name Seagate Technology url www.seagate.com ansi_color 0;92;100 match_string Seagate -# match_string_case ST + match_string_num_prefix_case ST name Silicon Integrated Systems Corporation name_short SIS @@ -719,6 +814,7 @@ name Infineon Technologies wikipedia Infineon Technologies ansi_color 0;34;107 match_string Infineon + match_string Infineon (former Siemens) name Cypress Semiconductor name_short Cypress @@ -744,6 +840,7 @@ name Victor Company of Japan url www.victor.co.jp ansi_color 0;91;107 match_string_case JVC + match_string Victor name ASRock url www.asrock.com @@ -814,6 +911,51 @@ name SK Hynix match_string Hynix match_string Hyundai +name PNY Technologies + name_short PNY + url www.pny.com + wikipedia PNY Technologies + ansi_color 0;97;100 + match_string_case PNY + +name Linaro + url linaro.org + wikipedia Linaro + ansi_color 0;32;107 + match_string Linaro + +name Longsys + name_short longsys + url longsys.com + ansi_color 0;31;107 + match_string Longsys + +name Longsys (formerly Micron Lexar) + name_short longsys/Lexar + url lexar.com + wikipedia Lexar + ansi_color 0;31;40 + match_string Lexar + +name Angelbird Technologies + name_short Angelbird + url www.angelbird.com + ansi_color 0;97;100 + match_string Angelbird + +name Hoodman Corporation + name_short Hoodman + url www.hoodmanusa.com + ansi_color 0;30;43 + match_string Hoodman + +name Silicon Power + name_short SP + url www.silicon-power.com + wikipedia Silicon Power + ansi_color 0;97;40 + match_string Silicon Power + # # BIOS manufacturers # @@ -884,17 +1026,20 @@ name Red Hat match_string Red Hat match_string RedHat -name Sun Microsystems - name_short Sun - wikipedia Sun Microsystems - match_string Sun Microsystems - name Oracle Corporation name_short Oracle url www.oracle.com ansi_color 0;97;41 match_string Oracle +name Oracle Corporation (formerly Sun Microsystems) + name_short Oracle (Sun) + url www.oracle.com + wikipedia Sun Microsystems + ansi_color 0;97;41 + match_string Sun Microsystems + match_string Oracle Corporation (former Sun Microsystems) + name Oracle Corporation (formerly InnoTek Systemberatung) name_short Oracle (InnoTek) url www.virtualbox.org/wiki/innotek @@ -1008,7 +1153,17 @@ name Digital Equipment Corporation note Dead; various parts to Intel, Compaq, HP match_string_case DEC match_string Digital Equipment - match_string Digital + match_string_exact Digital + +name Western Digital + name_short WD + url www.westerndigital.com + wikipedia Western Digital + ansi_color 0;37;40 +# ansi_color 0;97;44 + match_string Western Digital + match_string_case WDC + match_string_num_prefix_case WD name Marvell Technology Group name_short Marvell @@ -1067,6 +1222,14 @@ name MediaTek ansi_color 0;97;43 match_string MediaTek +name Valve Corporation + name_short VALVE + url valvesoftware.com + wikipedia Valve Corporation + ansi_color 0;97;41 + match_string Valve Corporation + match_string Valve + # # x86 VM vendor strings # diff --git a/deps/sysobj_early/include/util_edid.h b/deps/sysobj_early/include/util_edid.h index b50dcb33..6f1360b5 100644 --- a/deps/sysobj_early/include/util_edid.h +++ b/deps/sysobj_early/include/util_edid.h @@ -24,6 +24,38 @@ #include <stdint.h> /* for *int*_t types */ typedef struct { + uint8_t version; + uint8_t extension_length; + uint8_t primary_use_case; + uint8_t extension_count; + int blocks; + int checksum_ok; +} DisplayIDMeta; + +typedef struct { + uint8_t *ptr; + union { + uint8_t tag; + uint8_t type; + }; + uint8_t revision; + uint8_t len; +} DisplayIDBlock; + +/* order by rising priority */ +enum { + OUTSRC_EDID, + OUTSRC_ETB, + OUTSRC_STD, + OUTSRC_DTD, + OUTSRC_CEA_DTD, + OUTSRC_SVD, + OUTSRC_DID_TYPE_I, + OUTSRC_DID_TYPE_VI, + OUTSRC_DID_TYPE_VII, +}; + +typedef struct { float horiz_cm, vert_cm; float diag_cm, diag_in; int horiz_blanking, vert_blanking; @@ -31,8 +63,9 @@ typedef struct { float vert_freq_hz; int is_interlaced; int stereo_mode; + int is_preferred; uint64_t pixel_clock_khz; - int src; /* 0: edid, 1: etb, 2: std, 3: dtd, 4: cea-dtd, 5: svd ... */ + int src; /* enum OUTSRC_* */ uint64_t pixels; /* h*v: easier to compare */ char class_inch[6]; } edid_output; @@ -71,6 +104,14 @@ struct edid_cea_block { int reserved[8]; }; +enum { + STD_EDID = 0, + STD_EEDID = 1, + STD_EIACEA861 = 2, + STD_DISPLAYID = 3, + STD_DISPLAYID20 = 4, +}; + typedef struct { union { void* data; @@ -80,10 +121,7 @@ typedef struct { }; unsigned int len; - /* 0 - EDID - * 1 - EIA/CEA-861 - * 2 - DisplayID - */ + /* enum STD_* */ int std; int ver_major, ver_minor; @@ -128,6 +166,12 @@ typedef struct { edid_output img_max; int speaker_alloc_bits; + DisplayIDMeta did; + int did_block_count; + DisplayIDBlock *did_blocks; + + int didt_count; + edid_output *didts; } edid; edid *edid_new(const char *data, unsigned int len); edid *edid_new_from_hex(const char *hex_string); @@ -147,6 +191,8 @@ char *edid_dtd_describe(struct edid_dtd *dtd, int dump_bytes); char *edid_cea_block_describe(struct edid_cea_block *blk); char *edid_cea_audio_describe(struct edid_sad *sad); char *edid_cea_speaker_allocation_describe(int bitfield, int short_version); +const char *edid_did_block_type(int type); +char *edid_did_block_describe(DisplayIDBlock *blk); char *edid_dump2(edid *e); diff --git a/deps/sysobj_early/src/util_edid.c b/deps/sysobj_early/src/util_edid.c index 2aa595fa..6d90f6ac 100644 --- a/deps/sysobj_early/src/util_edid.c +++ b/deps/sysobj_early/src/util_edid.c @@ -31,16 +31,19 @@ #include "util_edid_svd_table.c" -/* block must be 128 bytes */ -static int block_check(const void *edid_block_bytes) { +static int block_check_n(const void *edid_block_bytes, int len) { if (!edid_block_bytes) return 0; uint8_t sum = 0; uint8_t *data = (uint8_t*)edid_block_bytes; int i; - for(i=0; i<128; i++) + for(i=0; i<len; i++) sum += data[i]; return sum == 0 ? 1 : 0; } +static int block_check(const void *edid_block_bytes) { + /* block must be 128 bytes */ + return block_check_n(edid_block_bytes, 128); +} char *hex_bytes(uint8_t *bytes, int count) { char *buffer = malloc(count*3+1), *p = buffer; @@ -53,6 +56,51 @@ char *hex_bytes(uint8_t *bytes, int count) { return buffer; } +#define OUTPUT_CPY_SIZE(DEST, SRC) \ + (DEST).horiz_cm = (SRC).horiz_cm; \ + (DEST).vert_cm = (SRC).vert_cm; \ + (DEST).diag_cm = (SRC).diag_cm; \ + (DEST).diag_in = (SRC).diag_in; \ + edid_output_fill(&(DEST)); + +static void edid_output_fill(edid_output *out) { + out->diag_cm = + sqrt( (out->horiz_cm * out->horiz_cm) + + (out->vert_cm * out->vert_cm) ); + out->diag_in = out->diag_cm / 2.54; + + if (out->is_interlaced) { + if (out->vert_lines) + out->vert_pixels = out->vert_lines * 2; + else + out->vert_lines = out->vert_pixels / 2; + } else { + if (out->vert_lines) + out->vert_pixels = out->vert_lines; + else + out->vert_lines = out->vert_pixels; + } + + if (!out->vert_freq_hz && out->pixel_clock_khz) { + uint64_t h = out->horiz_pixels + out->horiz_blanking; + uint64_t v = out->vert_lines + out->vert_blanking; + if (h && v) { + uint64_t work = out->pixel_clock_khz * 1000; + work /= (h*v); + out->vert_freq_hz = work; + } + } + + out->pixels = out->horiz_pixels; + out->pixels *= out->vert_pixels; + + if (out->diag_in) { + static const char *inlbl = "\""; /* TODO: unicode */ + sprintf(out->class_inch, "%0.1f%s", out->diag_in, inlbl); + util_strchomp_float(out->class_inch); + } +} + static void cea_block_decode(struct edid_cea_block *blk, edid *e) { int i; if (blk) { @@ -90,45 +138,77 @@ static void cea_block_decode(struct edid_cea_block *blk, edid *e) { } } -static void edid_output_fill(edid_output *out) { - out->diag_cm = - sqrt( (out->horiz_cm * out->horiz_cm) - + (out->vert_cm * out->vert_cm) ); - out->diag_in = out->diag_cm / 2.54; - - if (out->is_interlaced) { - if (out->vert_lines) - out->vert_pixels = out->vert_lines * 2; - else - out->vert_lines = out->vert_pixels / 2; - } else { - if (out->vert_lines) - out->vert_pixels = out->vert_lines; - else - out->vert_lines = out->vert_pixels; - } - - if (!out->vert_freq_hz && out->pixel_clock_khz) { - uint64_t h = out->horiz_pixels + out->horiz_blanking; - uint64_t v = out->vert_lines + out->vert_blanking; - if (h && v) { - uint64_t work = out->pixel_clock_khz * 1000; - work /= (h*v); - out->vert_freq_hz = work; +static void did_block_decode(DisplayIDBlock *blk, edid *e) { + int b = 3; + uint8_t *u8 = blk->ptr; + edid_output out = {}; + if (blk) { + switch(blk->type) { + case 0x03: /* Type I Detailed timings */ + out.pixel_clock_khz = u8[b+2] << 16; + out.pixel_clock_khz += u8[b+1] << 8; + out.pixel_clock_khz += u8[b]; + out.pixel_clock_khz *= 10; + out.horiz_pixels = (u8[b+5] << 8) + u8[b+4]; + out.horiz_blanking = (u8[b+7] << 8) + u8[b+6]; + out.vert_lines = (u8[b+13] << 8) + u8[b+12]; + out.vert_blanking = (u8[b+15] << 8) + u8[b+14]; + out.is_interlaced = (u8[b+3] >> 4) & 0x1; + out.stereo_mode = (u8[b+3] >> 5) & 0x2; + out.is_preferred = (u8[b+3] >> 7) & 0x1; + out.src = OUTSRC_DID_TYPE_I; + edid_output_fill(&out); + e->didts[e->didt_count++] = out; + break; + case 0x13: /* Type VI Detailed timings (super 0x03) */ + /* UNTESTED */ + out.pixel_clock_khz = (u8[b+2] << 16) & 0xa0; + out.pixel_clock_khz += u8[b+1] << 8; + out.pixel_clock_khz += u8[b]; + out.horiz_pixels = ((u8[b+5] << 8) + u8[b+3]) & 0x7fff; + out.vert_lines = ((u8[b+6] << 8) + u8[b+5]) & 0x7fff; + // TODO: blanking... + out.is_interlaced = (u8[b+13] >> 7) & 0x1; + out.stereo_mode = (u8[b+13] >> 5) & 0x2; + out.src = OUTSRC_DID_TYPE_VI; + edid_output_fill(&out); + e->didts[e->didt_count++] = out; + break; + case 0x22: /* Type VII Detailed timings (super 0x13) */ + /* UNTESTED */ + out.pixel_clock_khz = u8[b+2] << 16; + out.pixel_clock_khz += u8[b+1] << 8; + out.pixel_clock_khz += u8[b]; + out.horiz_pixels = (u8[b+5] << 8) + u8[b+4]; + out.horiz_blanking = (u8[b+7] << 8) + u8[b+6]; + out.vert_lines = (u8[b+13] << 8) + u8[b+12]; + out.vert_blanking = (u8[b+15] << 8) + u8[b+14]; + out.is_interlaced = (u8[b+3] >> 4) & 0x1; + out.stereo_mode = (u8[b+3] >> 5) & 0x2; + out.is_preferred = (u8[b+3] >> 7) & 0x1; + out.src = OUTSRC_DID_TYPE_VII; + edid_output_fill(&out); + e->didts[e->didt_count++] = out; + break; + case 0x81: /* CTA DisplayID, ... Embedded CEA Blocks */ + while(b < blk->len) { + int db_type = (u8[b] & 0xe0) >> 5; + int db_size = u8[b] & 0x1f; + e->cea_blocks[e->cea_block_count].header.ptr = &u8[b]; + e->cea_blocks[e->cea_block_count].header.type = db_type; + e->cea_blocks[e->cea_block_count].header.len = db_size; + cea_block_decode(&e->cea_blocks[e->cea_block_count], e); + e->cea_block_count++; + b += db_size + 1; + } + break; + default: + break; } } - - out->pixels = out->horiz_pixels; - out->pixels *= out->vert_pixels; - - if (out->diag_in) { - static const char *inlbl = "\""; /* TODO: unicode */ - sprintf(out->class_inch, "%0.1f%s", out->diag_in, inlbl); - util_strchomp_float(out->class_inch); - } } -edid_output edid_output_from_svd(uint8_t index) { +static edid_output edid_output_from_svd(uint8_t index) { int i; if (index >= 128 && index <= 192) index &= 0x7f; /* "native" flag for 0-64 */ for(i = 0; i < (int)G_N_ELEMENTS(cea_standard_timings); i++) { @@ -140,7 +220,7 @@ edid_output edid_output_from_svd(uint8_t index) { out.is_interlaced = 1; out.pixel_clock_khz = cea_standard_timings[i].pixel_clock_mhz * 1000; out.vert_freq_hz = cea_standard_timings[i].vert_freq_hz; - out.src = 5; + out.src = OUTSRC_SVD; edid_output_fill(&out); return out; } @@ -160,14 +240,19 @@ edid *edid_new(const char *data, unsigned int len) { e->ver_major = e->u8[18]; e->ver_minor = e->u8[19]; - e->dtds = malloc(sizeof(struct edid_dtd) * 1000); - e->cea_blocks = malloc(sizeof(struct edid_cea_block) * 1000); - e->svds = malloc(sizeof(struct edid_svd) * 1000); - e->sads = malloc(sizeof(struct edid_sad) * 1000); - memset(e->dtds, 0, sizeof(struct edid_dtd) * 1000); - memset(e->cea_blocks, 0, sizeof(struct edid_cea_block) * 1000); - memset(e->svds, 0, sizeof(struct edid_svd) * 1000); - memset(e->sads, 0, sizeof(struct edid_sad) * 1000); +#define RESERVE_COUNT 300 + e->dtds = malloc(sizeof(struct edid_dtd) * RESERVE_COUNT); + e->cea_blocks = malloc(sizeof(struct edid_cea_block) * RESERVE_COUNT); + e->svds = malloc(sizeof(struct edid_svd) * RESERVE_COUNT); + e->sads = malloc(sizeof(struct edid_sad) * RESERVE_COUNT); + e->did_blocks = malloc(sizeof(DisplayIDBlock) * RESERVE_COUNT); + e->didts = malloc(sizeof(edid_output) * RESERVE_COUNT); + memset(e->dtds, 0, sizeof(struct edid_dtd) * RESERVE_COUNT); + memset(e->cea_blocks, 0, sizeof(struct edid_cea_block) * RESERVE_COUNT); + memset(e->svds, 0, sizeof(struct edid_svd) * RESERVE_COUNT); + memset(e->sads, 0, sizeof(struct edid_sad) * RESERVE_COUNT); + memset(e->did_blocks, 0, sizeof(DisplayIDBlock) * RESERVE_COUNT); + memset(e->didts, 0, sizeof(edid_output) * RESERVE_COUNT); uint16_t vid = be16toh(e->u16[4]); /* bytes 8-9 */ e->ven[2] = 64 + (vid & 0x1f); @@ -210,7 +295,7 @@ edid *edid_new(const char *data, unsigned int len) { e->etbs[e->etb_count].vert_pixels = v; \ e->etbs[e->etb_count].vert_freq_hz = f; \ e->etbs[e->etb_count].is_interlaced = i; \ - e->etbs[e->etb_count].src = 1; \ + e->etbs[e->etb_count].src = OUTSRC_ETB; \ edid_output_fill(&e->etbs[e->etb_count]);\ e->etb_count++; }; ETB_CHECK(35, 7, 720, 400, 70, 0); //(VGA) @@ -262,7 +347,7 @@ edid *edid_new(const char *data, unsigned int len) { e->stds[e->std_count].out.horiz_pixels = xres; e->stds[e->std_count].out.vert_pixels = yres; e->stds[e->std_count].out.vert_freq_hz = vf; - e->stds[e->std_count].out.src = 2; + e->stds[e->std_count].out.src = OUTSRC_STD; edid_output_fill(&e->stds[e->std_count].out); e->std_count++; } @@ -299,13 +384,41 @@ edid *edid_new(const char *data, unsigned int len) { else e->ext_blocks_fail++; if (u8[0] == 0x70) { - e->std = MAX(e->std, 2); /* DisplayID */ - // TODO: ... + e->did.version = u8[1]; + if (e->did.version >= 0x20) + e->std = MAX(e->std, STD_DISPLAYID20); + else e->std = MAX(e->std, STD_DISPLAYID); + e->did.extension_length = u8[2]; + e->did.primary_use_case = u8[3]; + e->did.extension_count = u8[4]; + int db_end = u8[2] + 5; + int b = 5; + while(b < db_end) { + int db_type = u8[b]; + int db_revision = u8[b+1] & 0x7; + int db_size = u8[b+2]; + e->did_blocks[e->did_block_count].ptr = &u8[b]; + e->did_blocks[e->did_block_count].type = db_type; + e->did_blocks[e->did_block_count].revision = db_revision; + e->did_blocks[e->did_block_count].len = db_size; + did_block_decode(&e->did_blocks[e->did_block_count], e); + e->did_block_count++; + e->did.blocks++; + b += db_size + 3; + } + if (b != db_end) { + // over or under-run ... + } + e->did.checksum_ok = block_check_n(u8, u8[2] + 5); + //printf("DID: v:%02x el:%d uc:%d ec:%d, blocks:%d ok:%d\n", + // e->did.version, e->did.extension_length, + // e->did.primary_use_case, e->did.extension_count, + // e->did.blocks, e->checksum_ok); } if (u8[0] == 0x02) { - e->std = MAX(e->std, 1); + e->std = MAX(e->std, STD_EIACEA861); /* CEA extension */ int db_end = u8[2]; if (db_end) { @@ -334,6 +447,9 @@ edid *edid_new(const char *data, unsigned int len) { } } } + if (e->ext_blocks_ok) { + e->std = MAX(e->std, STD_EEDID); + } /* strings */ for(i = 0; i < 4; i++) { @@ -389,8 +505,8 @@ edid *edid_new(const char *data, unsigned int len) { uint8_t *u8 = e->dtds[i].ptr; uint16_t *u16 = (uint16_t*)e->dtds[i].ptr; edid_output *out = &e->dtds[i].out; - if (e->dtds[i].cea_ext) out->src = 4; - else out->src = 3; + if (e->dtds[i].cea_ext) out->src = OUTSRC_CEA_DTD; + else out->src = OUTSRC_DTD; out->pixel_clock_khz = le16toh(u16[0]) * 10; out->horiz_pixels = ((u8[4] & 0xf0) << 4) + u8[2]; @@ -421,42 +537,51 @@ edid *edid_new(const char *data, unsigned int len) { /* svds */ for(i = 0; i < e->svd_count; i++) { + e->svds[i].out = edid_output_from_svd(e->svds[i].v); if (e->svds[i].v >= 128 && e->svds[i].v <= 192) { e->svds[i].is_native = 1; + + edid_output tmp = e->img_max; + /* native res is max real res, right? */ + e->img_max = e->svds[i].out; + e->img_max.is_preferred = 1; + OUTPUT_CPY_SIZE(e->img_max, tmp); } - e->svds[i].out = edid_output_from_svd(e->svds[i].v); } - /* squeeze lists */ - if (!e->dtd_count) { - free(e->dtds); - e->dtds = NULL; - } else { - e->dtds = realloc(e->dtds, sizeof(struct edid_dtd) * e->dtd_count); - } - if (!e->cea_block_count) { - if (e->cea_blocks) - free(e->cea_blocks); - e->cea_blocks = NULL; - } else { - e->cea_blocks = realloc(e->cea_blocks, sizeof(struct edid_cea_block) * e->cea_block_count); - } - if (!e->svd_count) { - if (e->svds) - free(e->svds); - e->svds = NULL; - } else { - e->svds = realloc(e->svds, sizeof(struct edid_svd) * e->svd_count); + /* didts */ + for(i = 0; i < e->didt_count; i++) { + int pref = e->didts[i].is_preferred; + int max_pref = e->img_max.is_preferred; + int bigger = (e->didts[i].pixels > e->img_max.pixels); + int better = (e->didts[i].src > e->img_max.src); + if (bigger && !max_pref + || pref && !max_pref + || pref && better) { + edid_output tmp = e->img_max; + e->img_max = e->didts[i]; + OUTPUT_CPY_SIZE(e->img_max, tmp); + } } - if (!e->sad_count) { - if (e->sads) - free(e->sads); - e->sads = NULL; - } else { - e->sads = realloc(e->sads, sizeof(struct edid_sad) * e->sad_count); + + if (!e->speaker_alloc_bits && e->sad_count) { + /* make an assumption */ + if (e->sads[0].channels == 2) + e->speaker_alloc_bits = 0x1; } + /* squeeze lists */ +#define SQUEEZE(C, L) \ + if (!e->C) { free(e->L); e->L = NULL; } \ + else { e->L = realloc(e->L, sizeof(e->L[0]) * (e->C)); } + + SQUEEZE(dtd_count, dtds); + SQUEEZE(cea_block_count, cea_blocks); + SQUEEZE(svd_count, svds); + SQUEEZE(sad_count, sads); + SQUEEZE(did_block_count, did_blocks); + SQUEEZE(didt_count, didts); return e; } @@ -528,20 +653,26 @@ edid_dump_hex_done: const char *edid_standard(int std) { switch(std) { - case 0: return N_("VESA EDID"); - case 1: return N_("EIA/CEA-861"); - case 2: return N_("VESA DisplayID"); + case STD_EDID: return N_("VESA EDID"); + case STD_EEDID: return N_("VESA E-EDID"); + case STD_EIACEA861: return N_("EIA/CEA-861"); + case STD_DISPLAYID: return N_("VESA DisplayID"); + case STD_DISPLAYID20: return N_("VESA DisplayID 2.0"); }; return N_("unknown"); } const char *edid_output_src(int src) { switch(src) { - case 0: return N_("VESA EDID"); - case 1: return N_("VESA EDID ETB"); - case 2: return N_("VESA EDID STD"); - case 3: return N_("VESA EDID DTD"); - case 4: return N_("EIA/CEA-861 DTD"); + case OUTSRC_EDID: return N_("VESA EDID"); + case OUTSRC_ETB: return N_("VESA EDID ETB"); + case OUTSRC_STD: return N_("VESA EDID STD"); + case OUTSRC_DTD: return N_("VESA EDID DTD"); + case OUTSRC_CEA_DTD: return N_("EIA/CEA-861 DTD"); + case OUTSRC_SVD: return N_("EIA/CEA-861 SVD"); + case OUTSRC_DID_TYPE_I: return N_("DisplayID Type I"); + case OUTSRC_DID_TYPE_VI: return N_("DisplayID Type VI"); + case OUTSRC_DID_TYPE_VII: return N_("DisplayID Type VII"); }; return N_("unknown"); } @@ -592,6 +723,46 @@ const char *edid_cea_block_type(int type) { return N_("unknown type"); } +const char *edid_did_block_type(int type) { + switch(type) { + /* 1.x */ + case 0x00: return N_("Product Identification (1.x)"); + case 0x01: return N_("Display Parameters (1.x)"); + case 0x02: return N_("Color Characteristics (1.x)"); + case 0x03: return N_("Type I Timing - Detailed (1.x)"); + case 0x04: return N_("Type II Timing - Detailed (1.x)"); + case 0x05: return N_("Type III Timing - Short (1.x)"); + case 0x06: return N_("Type IV Timing - DMT ID Code (1.x)"); + case 0x07: return N_("VESA Timing Standard (1.x)"); + case 0x08: return N_("CEA Timing Standard (1.x)"); + case 0x09: return N_("Video Timing Range (1.x)"); + case 0x0A: return N_("Product Serial Number (1.x)"); + case 0x0B: return N_("General Purpose ASCII String (1.x)"); + case 0x0C: return N_("Display Device Data (1.x)"); + case 0x0D: return N_("Interface Power Sequencing (1.x)"); + case 0x0E: return N_("Transfer Characteristics (1.x)"); + case 0x0F: return N_("Display Interface Data (1.x)"); + case 0x10: return N_("Stereo Display Interface (1.x)"); + case 0x11: return N_("Type V Timing - Short (1.x)"); + case 0x13: return N_("Type VI Timing - Detailed (1.x)"); + case 0x7F: return N_("Vendor specific (1.x)"); + /* 2.x */ + case 0x20: return N_("Product Identification"); + case 0x21: return N_("Display Parameters"); + case 0x22: return N_("Type VII - Detailed Timing"); + case 0x23: return N_("Type VIII - Enumerated Timing Code"); + case 0x24: return N_("Type IX - Formula-based Timing"); + case 0x25: return N_("Dynamic Video Timing Range Limits"); + case 0x26: return N_("Display Interface Features"); + case 0x27: return N_("Stereo Display Interface"); + case 0x28: return N_("Tiled Display Topology"); + case 0x29: return N_("ContainerID"); + case 0x7E: return N_("Vendor specific"); + case 0x81: return N_("CTA DisplayID"); + } + return N_("unknown type"); +} + const char *edid_ext_block_type(int type) { switch(type) { case 0x00: @@ -735,6 +906,23 @@ char *edid_cea_block_describe(struct edid_cea_block *blk) { return ret; } +char *edid_did_block_describe(DisplayIDBlock *blk) { + gchar *ret = NULL; + if (blk) { + char *hb = hex_bytes(blk->ptr, blk->len+3); + switch(blk->type) { + default: + ret = g_strdup_printf("([%02x:r%02x] %s) len:%d -- %s", + blk->type, blk->revision, _(edid_did_block_type(blk->type)), + blk->len, + hb); + break; + } + free(hb); + } + return ret; +} + char *edid_output_describe(edid_output *out) { gchar *ret = NULL; if (out) { @@ -837,6 +1025,7 @@ char *edid_dump2(edid *e) { for(i = 0; i < e->cea_block_count; i++) { char *desc = edid_cea_block_describe(&e->cea_blocks[i]); ret = appfnl(ret, "cea_block[%d] %s", i, desc); + free(desc); } for(i = 0; i < e->svd_count; i++) { @@ -853,6 +1042,18 @@ char *edid_dump2(edid *e) { free(desc); } + for(i = 0; i < e->did_block_count; i++) { + char *desc = edid_did_block_describe(&e->did_blocks[i]); + ret = appfnl(ret, "did_block[%d] %s", i, desc); + free(desc); + } + + for(i = 0; i < e->didt_count; i++) { + char *desc = edid_output_describe(&e->didts[i]); + ret = appfnl(ret, "did_timing[%d]: %s", i, desc); + g_free(desc); + } + return ret; } |