aboutsummaryrefslogtreecommitdiff
path: root/deps/sysobj_early/src/util_edid.c
diff options
context:
space:
mode:
Diffstat (limited to 'deps/sysobj_early/src/util_edid.c')
-rw-r--r--deps/sysobj_early/src/util_edid.c100
1 files changed, 77 insertions, 23 deletions
diff --git a/deps/sysobj_early/src/util_edid.c b/deps/sysobj_early/src/util_edid.c
index 7b004dc9..936744e0 100644
--- a/deps/sysobj_early/src/util_edid.c
+++ b/deps/sysobj_early/src/util_edid.c
@@ -29,6 +29,8 @@
#include "util_edid.h"
#include "util_sysobj.h"
+#include "util_edid_svd_table.c"
+
/* block must be 128 bytes */
static int block_check(const void *edid_block_bytes) {
if (!edid_block_bytes) return 0;
@@ -53,9 +55,8 @@ char *hex_bytes(uint8_t *bytes, int count) {
static void cea_block_decode(struct edid_cea_block *blk) {
struct edid_cea_audio *blk_audio = (void*)blk;
- struct edid_cea_video *blk_video = (void*)blk;
struct edid_cea_speaker *blk_speaker = (void*)blk;
- struct edid_cea_vendor_spec *blk_vendor_spec = (void*)blk;
+ //struct edid_cea_vendor_spec *blk_vendor_spec = (void*)blk;
if (blk) {
switch(blk->header.type) {
case 0x1:
@@ -73,7 +74,7 @@ static void cea_block_decode(struct edid_cea_block *blk) {
blk_speaker->alloc_bits = blk->header.ptr[1];
break;
case 0x3:
- case 0x2:
+ case 0x2: /* SVD list is handled elsewhere */
default:
break;
}
@@ -101,17 +102,41 @@ static void edid_output_fill(edid_output *out) {
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;
- uint64_t work = out->pixel_clock_khz * 1000;
- work /= (h*v);
- out->vert_freq_hz = work;
+ 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;
- static const char *inlbl = "\""; /* TODO: unicode */
- sprintf(out->class_inch, "%0.1f%s", out->diag_in, inlbl);
- util_strchomp_float(out->class_inch);
+ 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) {
+ 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++) {
+ if (cea_standard_timings[i].index == index) {
+ edid_output out = {};
+ out.horiz_pixels = cea_standard_timings[i].horiz_active;
+ out.vert_lines = cea_standard_timings[i].vert_active;
+ if (strchr(cea_standard_timings[i].short_name, 'i'))
+ 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;
+ edid_output_fill(&out);
+ return out;
+ }
+ }
+ return (edid_output){};
}
edid *edid_new(const char *data, unsigned int len) {
@@ -128,8 +153,10 @@ edid *edid_new(const char *data, unsigned int len) {
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);
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);
uint16_t vid = be16toh(e->u16[4]); /* bytes 8-9 */
e->ven[2] = 64 + (vid & 0x1f);
@@ -196,7 +223,7 @@ edid *edid_new(const char *data, unsigned int len) {
/* standard timings */
for(i = 38; i < 53; i+=2) {
/* 0101 is unused */
- if (e->u8[i] == 0x01 && e->u8[i] == 0x01)
+ if (e->u8[i] == 0x01 && e->u8[i+1] == 0x01)
continue;
double xres = (e->u8[i] + 31) * 8;
double yres = 0;
@@ -270,26 +297,26 @@ edid *edid_new(const char *data, unsigned int len) {
e->std = MAX(e->std, 1);
/* CEA extension */
int db_end = u8[2];
- //printf("db_end: %d\n", db_end);
if (db_end) {
int b = 4;
while(b < db_end) {
int db_type = (u8[b] & 0xe0) >> 5;
int db_size = u8[b] & 0x1f;
- //printf("CEA BLK: %s\n", hex_bytes(&u8[b], db_size+1));
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]);
+ if (db_type == 0x2) {
+ for(i = 1; i <= db_size; i++)
+ e->svds[e->svd_count++].v = u8[b+i];
+ } else
+ cea_block_decode(&e->cea_blocks[e->cea_block_count]);
e->cea_block_count++;
b += db_size + 1;
}
if (b > db_end) b = db_end;
- //printf("dtd start: %d\n", b);
/* DTDs */
while(b < 127) {
if (u8[b]) {
- //printf("DTD: %s\n", hex_bytes(&u8[b], 18));
e->dtds[e->dtd_count].ptr = &u8[b];
e->dtds[e->dtd_count].cea_ext = 1;
e->dtd_count++;
@@ -385,6 +412,15 @@ edid *edid_new(const char *data, unsigned int len) {
e->img_max = e->dtds[0].out;
}
+ /* svds */
+ for(i = 0; i < e->svd_count; i++) {
+ if (e->svds[i].v >= 128 &&
+ e->svds[i].v <= 192) {
+ e->svds[i].is_native = 1;
+ }
+ e->svds[i].out = edid_output_from_svd(e->svds[i].v);
+ }
+
/* squeeze lists */
if (!e->dtd_count) {
free(e->dtds);
@@ -399,6 +435,13 @@ edid *edid_new(const char *data, unsigned int len) {
} 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);
+ }
return e;
}
@@ -596,9 +639,8 @@ char *edid_cea_block_describe(struct edid_cea_block *blk) {
gchar *ret = NULL;
gchar *tmp[3] = {};
struct edid_cea_audio *blk_audio = (void*)blk;
- struct edid_cea_video *blk_video = (void*)blk;
struct edid_cea_speaker *blk_speaker = (void*)blk;
- struct edid_cea_vendor_spec *blk_vendor_spec = (void*)blk;
+ //struct edid_cea_vendor_spec *blk_vendor_spec = (void*)blk;
if (blk) {
char *hb = hex_bytes(blk->header.ptr, blk->header.len+1);
@@ -653,8 +695,12 @@ char *edid_cea_block_describe(struct edid_cea_block *blk) {
hb);
g_free(tmp[0]);
break;
- case 0x3:
case 0x2:
+ ret = g_strdup_printf("([%x] %s) svds:%d",
+ blk->header.type, _(edid_cea_block_type(blk->header.type)),
+ blk->header.len);
+ break;
+ case 0x3: //TODO
default:
ret = g_strdup_printf("([%x] %s) len:%d -- %s",
blk->header.type, _(edid_cea_block_type(blk->header.type)),
@@ -670,11 +716,13 @@ char *edid_cea_block_describe(struct edid_cea_block *blk) {
char *edid_output_describe(edid_output *out) {
gchar *ret = NULL;
if (out) {
- ret = g_strdup_printf("%dx%d@%.0f%s, %0.1fx%0.1f%s (%0.1f\") %s %s",
- out->horiz_pixels, out->vert_pixels, out->vert_freq_hz, _("Hz"),
- out->horiz_cm, out->vert_cm, _("cm"), out->diag_in,
- out->is_interlaced ? "interlaced" : "progressive",
- out->stereo_mode ? "stereo" : "normal");
+ ret = g_strdup_printf("%dx%d@%.0f%s",
+ out->horiz_pixels, out->vert_pixels, out->vert_freq_hz, _("Hz") );
+ if (out->diag_cm)
+ ret = appfsp(ret, "%0.1fx%0.1f%s (%0.1f\")",
+ out->horiz_cm, out->vert_cm, _("cm"), out->diag_in );
+ ret = appfsp(ret, "%s", out->is_interlaced ? "interlaced" : "progressive");
+ ret = appfsp(ret, "%s", out->stereo_mode ? "stereo" : "normal");
}
return ret;
}
@@ -763,6 +811,12 @@ char *edid_dump2(edid *e) {
ret = appfnl(ret, "cea_block[%d] %s", i, desc);
}
+ for(i = 0; i < e->svd_count; i++) {
+ char *desc = edid_output_describe(&e->svds[i].out);
+ ret = appfnl(ret, "svd[%d] [%02x] %s", i, e->svds[i].v, desc);
+ free(desc);
+ }
+
return ret;
}