edid: Clean-up the edid struct

There are serveral members of the edid struct which are never used
outside of the EDID parsing code itself. This patch moves them to a
struct in edid.c. They might be useful some day but until then we can
just pretty print them and not pollute the more general API.

BUG=none
BRANCH=firmware-veyron
TEST=compiled for veyron_mickey, peppy, link, nyan_big, rush, smaug
Signed-off-by: David Hendricks <dhendrix@chromium.org>

Change-Id: I660f28c850163e89fe1f59d6c5cfd6e63a56dda0
Signed-off-by: Patrick Georgi <patrick@georgi-clan.de>
Original-Commit-Id: ee8ea314a0d8f5993508f560fc24ab17604049df
Original-Change-Id: I7fb8674619c0b780cc64f3ab786286225a3fe0e2
Original-Reviewed-on: https://chromium-review.googlesource.com/290333
Original-Reviewed-by: Yakir Yang <ykk@rock-chips.com>
Original-Reviewed-by: Julius Werner <jwerner@chromium.org>
Original-Commit-Queue: David Hendricks <dhendrix@chromium.org>
Original-Tested-by: David Hendricks <dhendrix@chromium.org>
Reviewed-on: http://review.coreboot.org/11387
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
David Hendricks 2015-08-02 18:07:48 -07:00 committed by Patrick Georgi
parent ffe63e2796
commit a3b898aaf0
2 changed files with 71 additions and 76 deletions

View File

@ -27,14 +27,6 @@
*/ */
struct edid { struct edid {
char manuf_name[4];
unsigned int model;
unsigned int serial;
unsigned int year;
unsigned int week;
unsigned int version[2];
unsigned int nonconformant;
unsigned int type;
/* These next three things used to all be called bpp. /* These next three things used to all be called bpp.
* Merriment ensued. The identifier * Merriment ensued. The identifier
* 'bpp' is herewith banished from our * 'bpp' is herewith banished from our
@ -56,17 +48,9 @@ struct edid {
* all over the place. * all over the place.
*/ */
unsigned int panel_bits_per_pixel; unsigned int panel_bits_per_pixel;
unsigned int xres;
unsigned int yres;
unsigned int voltage;
unsigned int sync;
unsigned int xsize_cm;
unsigned int ysize_cm;
/* used to compute timing for graphics chips. */ /* used to compute timing for graphics chips. */
unsigned char phsync; unsigned char phsync;
unsigned char pvsync; unsigned char pvsync;
unsigned int x_mm;
unsigned int y_mm;
unsigned int pixel_clock; unsigned int pixel_clock;
unsigned int link_clock; unsigned int link_clock;
unsigned int ha; unsigned int ha;
@ -87,14 +71,6 @@ struct edid {
u32 x_resolution; u32 x_resolution;
u32 y_resolution; u32 y_resolution;
u32 bytes_per_line; u32 bytes_per_line;
/* it is unlikely we need these things. */
/* if one of these is non-zero, use that one. */
/* they're aspect * 10 to provide some additional resolution */
unsigned int aspect_landscape;
unsigned int aspect_portrait;
const char *range_class;
const char *syncmethod;
const char *stereo;
}; };
/* Defined in src/lib/edid.c */ /* Defined in src/lib/edid.c */

View File

@ -68,20 +68,43 @@ struct edid_context {
int conformant; int conformant;
}; };
/* Stuff that isn't used anywhere but is nice to pretty-print while
we're decoding everything else. */
static struct {
char manuf_name[4];
unsigned int model;
unsigned int serial;
unsigned int year;
unsigned int week;
unsigned int version[2];
unsigned int nonconformant;
unsigned int type;
unsigned int x_mm;
unsigned int y_mm;
unsigned int voltage;
unsigned int sync;
const char *syncmethod;
const char *range_class;
const char *stereo;
} extra_info;
static int vbe_valid; static int vbe_valid;
static struct lb_framebuffer edid_fb; static struct lb_framebuffer edid_fb;
static char *manufacturer_name(struct edid *out, unsigned char *x) static char *manufacturer_name(unsigned char *x)
{ {
out->manuf_name[0] = ((x[0] & 0x7C) >> 2) + '@'; extra_info.manuf_name[0] = ((x[0] & 0x7C) >> 2) + '@';
out->manuf_name[1] = ((x[0] & 0x03) << 3) + ((x[1] & 0xE0) >> 5) + '@'; extra_info.manuf_name[1] = ((x[0] & 0x03) << 3) + ((x[1] & 0xE0) >> 5) + '@';
out->manuf_name[2] = (x[1] & 0x1F) + '@'; extra_info.manuf_name[2] = (x[1] & 0x1F) + '@';
out->manuf_name[3] = 0; extra_info.manuf_name[3] = 0;
if (isupper(out->manuf_name[0]) && if (isupper(extra_info.manuf_name[0]) &&
isupper(out->manuf_name[1]) && isupper(extra_info.manuf_name[1]) &&
isupper(out->manuf_name[2])) isupper(extra_info.manuf_name[2]))
return out->manuf_name; return extra_info.manuf_name;
return NULL; return NULL;
} }
@ -258,7 +281,7 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension,
int v_max_offset = 0, v_min_offset = 0; int v_max_offset = 0, v_min_offset = 0;
int is_cvt = 0; int is_cvt = 0;
c->has_range_descriptor = 1; c->has_range_descriptor = 1;
out->range_class = ""; extra_info.range_class = "";
/* /*
* XXX todo: implement feature flags, vtd blocks * XXX todo: implement feature flags, vtd blocks
* XXX check: ranges are well-formed; block termination if no vtd * XXX check: ranges are well-formed; block termination if no vtd
@ -285,25 +308,25 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension,
*/ */
switch (x[10]) { switch (x[10]) {
case 0x00: /* default gtf */ case 0x00: /* default gtf */
out->range_class = "GTF"; extra_info.range_class = "GTF";
break; break;
case 0x01: /* range limits only */ case 0x01: /* range limits only */
out->range_class = "bare limits"; extra_info.range_class = "bare limits";
if (!c->claims_one_point_four) if (!c->claims_one_point_four)
c->has_valid_range_descriptor = 0; c->has_valid_range_descriptor = 0;
break; break;
case 0x02: /* secondary gtf curve */ case 0x02: /* secondary gtf curve */
out->range_class = "GTF with icing"; extra_info.range_class = "GTF with icing";
break; break;
case 0x04: /* cvt */ case 0x04: /* cvt */
out->range_class = "CVT"; extra_info.range_class = "CVT";
is_cvt = 1; is_cvt = 1;
if (!c->claims_one_point_four) if (!c->claims_one_point_four)
c->has_valid_range_descriptor = 0; c->has_valid_range_descriptor = 0;
break; break;
default: /* invalid */ default: /* invalid */
c->has_valid_range_descriptor = 0; c->has_valid_range_descriptor = 0;
out->range_class = "invalid"; extra_info.range_class = "invalid";
break; break;
} }
@ -312,7 +335,7 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension,
if (x[7] + h_min_offset > x[8] + h_max_offset) if (x[7] + h_min_offset > x[8] + h_max_offset)
c->has_valid_range_descriptor = 0; c->has_valid_range_descriptor = 0;
printk(BIOS_SPEW, "Monitor ranges (%s): %d-%dHz V, %d-%dkHz H", printk(BIOS_SPEW, "Monitor ranges (%s): %d-%dHz V, %d-%dkHz H",
out->range_class, extra_info.range_class,
x[5] + v_min_offset, x[6] + v_max_offset, x[5] + v_min_offset, x[6] + v_max_offset,
x[7] + h_min_offset, x[8] + h_max_offset); x[7] + h_min_offset, x[8] + h_max_offset);
if (x[9]) if (x[9])
@ -423,8 +446,8 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension,
if (! c->did_detailed_timing){ if (! c->did_detailed_timing){
/* Edid contains pixel clock in terms of 10KHz */ /* Edid contains pixel clock in terms of 10KHz */
out->pixel_clock = (x[0] + (x[1] << 8)) * 10; out->pixel_clock = (x[0] + (x[1] << 8)) * 10;
out->x_mm = (x[12] + ((x[14] & 0xF0) << 4)); extra_info.x_mm = (x[12] + ((x[14] & 0xF0) << 4));
out->y_mm = (x[13] + ((x[14] & 0x0F) << 8)); extra_info.y_mm = (x[13] + ((x[14] & 0x0F) << 8));
out->ha = (x[2] + ((x[4] & 0xF0) << 4)); out->ha = (x[2] + ((x[4] & 0xF0) << 4));
out->hbl = (x[3] + ((x[4] & 0x0F) << 8)); out->hbl = (x[3] + ((x[4] & 0x0F) << 8));
out->hso = (x[8] + ((x[11] & 0xC0) << 2)); out->hso = (x[8] + ((x[11] & 0xC0) << 2));
@ -464,41 +487,41 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension,
c->did_detailed_timing = 1; c->did_detailed_timing = 1;
switch ((x[17] & 0x18) >> 3) { switch ((x[17] & 0x18) >> 3) {
case 0x00: case 0x00:
out->syncmethod = " analog composite"; extra_info.syncmethod = " analog composite";
break; break;
case 0x01: case 0x01:
out->syncmethod = " bipolar analog composite"; extra_info.syncmethod = " bipolar analog composite";
break; break;
case 0x02: case 0x02:
out->syncmethod = " digital composite"; extra_info.syncmethod = " digital composite";
break; break;
case 0x03: case 0x03:
out->syncmethod = ""; extra_info.syncmethod = "";
break; break;
} }
out->pvsync = (x[17] & (1 << 2)) ? '+' : '-'; out->pvsync = (x[17] & (1 << 2)) ? '+' : '-';
out->phsync = (x[17] & (1 << 1)) ? '+' : '-'; out->phsync = (x[17] & (1 << 1)) ? '+' : '-';
switch (x[17] & 0x61) { switch (x[17] & 0x61) {
case 0x20: case 0x20:
out->stereo = "field sequential L/R"; extra_info.stereo = "field sequential L/R";
break; break;
case 0x40: case 0x40:
out->stereo = "field sequential R/L"; extra_info.stereo = "field sequential R/L";
break; break;
case 0x21: case 0x21:
out->stereo = "interleaved right even"; extra_info.stereo = "interleaved right even";
break; break;
case 0x41: case 0x41:
out->stereo = "interleaved left even"; extra_info.stereo = "interleaved left even";
break; break;
case 0x60: case 0x60:
out->stereo = "four way interleaved"; extra_info.stereo = "four way interleaved";
break; break;
case 0x61: case 0x61:
out->stereo = "side by side interleaved"; extra_info.stereo = "side by side interleaved";
break; break;
default: default:
out->stereo = ""; extra_info.stereo = "";
break; break;
} }
@ -507,15 +530,15 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension,
" %04x %04x %04x %04x vborder %x\n" " %04x %04x %04x %04x vborder %x\n"
" %chsync %cvsync%s%s %s\n", " %chsync %cvsync%s%s %s\n",
out->pixel_clock, out->pixel_clock,
out->x_mm, extra_info.x_mm,
out->y_mm, extra_info.y_mm,
out->ha, out->ha + out->hso, out->ha + out->hso + out->hspw, out->ha, out->ha + out->hso, out->ha + out->hso + out->hspw,
out->ha + out->hbl, out->hborder, out->ha + out->hbl, out->hborder,
out->va, out->va + out->vso, out->va + out->vso + out->vspw, out->va, out->va + out->vso, out->va + out->vso + out->vspw,
out->va + out->vbl, out->vborder, out->va + out->vbl, out->vborder,
out->phsync, out->pvsync, out->phsync, out->pvsync,
out->syncmethod, x[17] & 0x80 ?" interlaced" : "", extra_info.syncmethod, x[17] & 0x80 ?" interlaced" : "",
out->stereo extra_info.stereo
); );
return 1; return 1;
} }
@ -983,15 +1006,15 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
} }
memset(out, 0, sizeof(*out)); memset(out, 0, sizeof(*out));
if (manufacturer_name(out, edid + 0x08)) if (manufacturer_name(edid + 0x08))
c.manufacturer_name_well_formed = 1; c.manufacturer_name_well_formed = 1;
out->model = (unsigned short)(edid[0x0A] + (edid[0x0B] << 8)); extra_info.model = (unsigned short)(edid[0x0A] + (edid[0x0B] << 8));
out->serial = (unsigned int)(edid[0x0C] + (edid[0x0D] << 8) extra_info.serial = (unsigned int)(edid[0x0C] + (edid[0x0D] << 8)
+ (edid[0x0E] << 16) + (edid[0x0F] << 24)); + (edid[0x0E] << 16) + (edid[0x0F] << 24));
printk(BIOS_SPEW, "Manufacturer: %s Model %x Serial Number %u\n", printk(BIOS_SPEW, "Manufacturer: %s Model %x Serial Number %u\n",
out->manuf_name, extra_info.manuf_name,
(unsigned short)(edid[0x0A] + (edid[0x0B] << 8)), (unsigned short)(edid[0x0A] + (edid[0x0B] << 8)),
(unsigned int)(edid[0x0C] + (edid[0x0D] << 8) (unsigned int)(edid[0x0C] + (edid[0x0D] << 8)
+ (edid[0x0E] << 16) + (edid[0x0F] << 24))); + (edid[0x0E] << 16) + (edid[0x0F] << 24)));
@ -1004,24 +1027,24 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
c.has_valid_year = 1; c.has_valid_year = 1;
printk(BIOS_SPEW, "Made week %hhd of model year %hhd\n", edid[0x10], printk(BIOS_SPEW, "Made week %hhd of model year %hhd\n", edid[0x10],
edid[0x11]); edid[0x11]);
out->week = edid[0x10]; extra_info.week = edid[0x10];
out->year = edid[0x11]; extra_info.year = edid[0x11];
} else { } else {
/* we know it's at least 2013, when this code was written */ /* we know it's at least 2013, when this code was written */
if (edid[0x11] + 90 <= 2013) { if (edid[0x11] + 90 <= 2013) {
c.has_valid_year = 1; c.has_valid_year = 1;
printk(BIOS_SPEW, "Made week %hhd of %d\n", printk(BIOS_SPEW, "Made week %hhd of %d\n",
edid[0x10], edid[0x11] + 1990); edid[0x10], edid[0x11] + 1990);
out->week = edid[0x10]; extra_info.week = edid[0x10];
out->year = edid[0x11] + 1990; extra_info.year = edid[0x11] + 1990;
} }
} }
} }
} }
printk(BIOS_SPEW, "EDID version: %hhd.%hhd\n", edid[0x12], edid[0x13]); printk(BIOS_SPEW, "EDID version: %hhd.%hhd\n", edid[0x12], edid[0x13]);
out->version[0] = edid[0x12]; extra_info.version[0] = edid[0x12];
out->version[1] = edid[0x13]; extra_info.version[1] = edid[0x13];
if (edid[0x12] == 1) { if (edid[0x12] == 1) {
if (edid[0x13] > 4) { if (edid[0x13] > 4) {
@ -1068,7 +1091,7 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
default: default:
c.nonconformant_digital_display = 1; c.nonconformant_digital_display = 1;
} }
out->type = edid[0x14] & 0x0f; extra_info.type = edid[0x14] & 0x0f;
} else if (c.claims_one_point_two) { } else if (c.claims_one_point_two) {
conformance_mask = 0x7E; conformance_mask = 0x7E;
if (edid[0x14] & 0x01) { if (edid[0x14] & 0x01) {
@ -1079,13 +1102,13 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
if (!c.nonconformant_digital_display) if (!c.nonconformant_digital_display)
c.nonconformant_digital_display = edid[0x14] & conformance_mask; c.nonconformant_digital_display = edid[0x14] & conformance_mask;
out->nonconformant = c.nonconformant_digital_display; extra_info.nonconformant = c.nonconformant_digital_display;
} else { } else {
analog = 1; analog = 1;
int voltage = (edid[0x14] & 0x60) >> 5; int voltage = (edid[0x14] & 0x60) >> 5;
int sync = (edid[0x14] & 0x0F); int sync = (edid[0x14] & 0x0F);
out->voltage = voltage; extra_info.voltage = voltage;
out->sync = sync; extra_info.sync = sync;
printk(BIOS_SPEW, "Analog display, Input voltage level: %s V\n", printk(BIOS_SPEW, "Analog display, Input voltage level: %s V\n",
voltage == 3 ? "0.7/0.7" : voltage == 3 ? "0.7/0.7" :
@ -1117,19 +1140,15 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
if (edid[0x15] && edid[0x16]) { if (edid[0x15] && edid[0x16]) {
printk(BIOS_SPEW, "Maximum image size: %d cm x %d cm\n", printk(BIOS_SPEW, "Maximum image size: %d cm x %d cm\n",
edid[0x15], edid[0x16]); edid[0x15], edid[0x16]);
out->xsize_cm = edid[0x15];
out->ysize_cm = edid[0x16];
} else if (c.claims_one_point_four && (edid[0x15] || edid[0x16])) { } else if (c.claims_one_point_four && (edid[0x15] || edid[0x16])) {
if (edid[0x15]) { /* edid[0x15] != 0 && edid[0x16] == 0 */ if (edid[0x15]) { /* edid[0x15] != 0 && edid[0x16] == 0 */
unsigned int ratio = 100000/(edid[0x15] + 99); unsigned int ratio = 100000/(edid[0x15] + 99);
printk(BIOS_SPEW, "Aspect ratio is %u.%03u (landscape)\n", printk(BIOS_SPEW, "Aspect ratio is %u.%03u (landscape)\n",
ratio / 1000, ratio % 1000); ratio / 1000, ratio % 1000);
out->aspect_landscape = ratio / 100;
} else { /* edid[0x15] == 0 && edid[0x16] != 0 */ } else { /* edid[0x15] == 0 && edid[0x16] != 0 */
unsigned int ratio = 100000/(edid[0x16] + 99); unsigned int ratio = 100000/(edid[0x16] + 99);
printk(BIOS_SPEW, "Aspect ratio is %u.%03u (portrait)\n", printk(BIOS_SPEW, "Aspect ratio is %u.%03u (portrait)\n",
ratio / 1000, ratio % 1000); ratio / 1000, ratio % 1000);
out->aspect_portrait = ratio / 100;
} }
} else { } else {
/* Either or both can be zero for 1.3 and before */ /* Either or both can be zero for 1.3 and before */