aboutsummaryrefslogtreecommitdiff
path: root/deps/sysobj_early
diff options
context:
space:
mode:
authorBurt P <pburt0@gmail.com>2019-08-20 03:21:31 -0500
committerLeandro A. F. Pereira <leandro@hardinfo.org>2019-08-22 23:10:17 +0200
commite6dcfd248363bf2dbaf65eec50efd7ee4e472d61 (patch)
tree3930b8977987d4a3b9117481d63cccb76f9db871 /deps/sysobj_early
parenta688b9caa64c1a75c8d151fa58ca74a94afe0d85 (diff)
monitors: some DisplayID support
Signed-off-by: Burt P <pburt0@gmail.com>
Diffstat (limited to 'deps/sysobj_early')
-rw-r--r--deps/sysobj_early/data/edid.ids1
-rw-r--r--deps/sysobj_early/data/vendor.ids189
-rw-r--r--deps/sysobj_early/include/util_edid.h56
-rw-r--r--deps/sysobj_early/src/util_edid.c379
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;
}