lib/edid.c: Differentiate between absent and non-conformant EDID
Change-Id: Id90aa210ff72092c4ab638a7bafb82bd11889bdc Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/19502 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Nico Huber <nico.h@gmx.de>
This commit is contained in:
parent
a459a8a145
commit
8c5884e8d7
|
@ -47,7 +47,7 @@ int ps8640_get_edid(uint8_t bus, uint8_t chip, struct edid *out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decode_edid(edid, edid_size, out)) {
|
if (decode_edid(edid, edid_size, out) != EDID_CONFORMANT) {
|
||||||
printk(BIOS_INFO, "Failed to decode EDID.\n");
|
printk(BIOS_INFO, "Failed to decode EDID.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,12 @@ struct edid {
|
||||||
int hdmi_monitor_detected;
|
int hdmi_monitor_detected;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum edid_status {
|
||||||
|
EDID_CONFORMANT,
|
||||||
|
EDID_NOT_CONFORMANT,
|
||||||
|
EDID_ABSENT,
|
||||||
|
};
|
||||||
|
|
||||||
/* Defined in src/lib/edid.c */
|
/* Defined in src/lib/edid.c */
|
||||||
int decode_edid(unsigned char *edid, int size, struct edid *out);
|
int decode_edid(unsigned char *edid, int size, struct edid *out);
|
||||||
void edid_set_framebuffer_bits_per_pixel(struct edid *edid, int fb_bpp,
|
void edid_set_framebuffer_bits_per_pixel(struct edid *edid, int fb_bpp,
|
||||||
|
|
|
@ -66,7 +66,7 @@ struct edid_context {
|
||||||
int seen_non_detailed_descriptor;
|
int seen_non_detailed_descriptor;
|
||||||
int warning_excessive_dotclock_correction;
|
int warning_excessive_dotclock_correction;
|
||||||
int warning_zero_preferred_refresh;
|
int warning_zero_preferred_refresh;
|
||||||
int conformant;
|
enum edid_status conformant;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Stuff that isn't used anywhere but is nice to pretty-print while
|
/* Stuff that isn't used anywhere but is nice to pretty-print while
|
||||||
|
@ -1134,7 +1134,7 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
|
||||||
.has_valid_range_descriptor = 1,
|
.has_valid_range_descriptor = 1,
|
||||||
.has_valid_max_dotclock = 1,
|
.has_valid_max_dotclock = 1,
|
||||||
.has_valid_string_termination = 1,
|
.has_valid_string_termination = 1,
|
||||||
.conformant = 1,
|
.conformant = EDID_CONFORMANT,
|
||||||
};
|
};
|
||||||
|
|
||||||
dump_breakdown(edid);
|
dump_breakdown(edid);
|
||||||
|
@ -1143,7 +1143,7 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
|
||||||
|
|
||||||
if (!edid || memcmp(edid, "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", 8)) {
|
if (!edid || memcmp(edid, "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", 8)) {
|
||||||
printk(BIOS_SPEW, "No header found\n");
|
printk(BIOS_SPEW, "No header found\n");
|
||||||
return 1;
|
return EDID_ABSENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manufacturer_name(edid + 0x08))
|
if (manufacturer_name(edid + 0x08))
|
||||||
|
@ -1485,11 +1485,12 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
|
||||||
if (c.nonconformant_digital_display ||
|
if (c.nonconformant_digital_display ||
|
||||||
!c.has_valid_string_termination ||
|
!c.has_valid_string_termination ||
|
||||||
!c.has_valid_descriptor_pad ||
|
!c.has_valid_descriptor_pad ||
|
||||||
!c.has_preferred_timing)
|
!c.has_preferred_timing) {
|
||||||
c.conformant = 0;
|
c.conformant = EDID_NOT_CONFORMANT;
|
||||||
if (!c.conformant)
|
|
||||||
printk(BIOS_ERR,
|
printk(BIOS_ERR,
|
||||||
"EDID block does NOT conform to EDID 1.4!\n");
|
"EDID block does NOT conform to EDID 1.4!\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (c.nonconformant_digital_display)
|
if (c.nonconformant_digital_display)
|
||||||
printk(BIOS_ERR,
|
printk(BIOS_ERR,
|
||||||
"\tDigital display field contains garbage: %x\n",
|
"\tDigital display field contains garbage: %x\n",
|
||||||
|
@ -1507,7 +1508,7 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
|
||||||
!c.has_valid_string_termination ||
|
!c.has_valid_string_termination ||
|
||||||
!c.has_valid_descriptor_pad ||
|
!c.has_valid_descriptor_pad ||
|
||||||
!c.has_preferred_timing) {
|
!c.has_preferred_timing) {
|
||||||
c.conformant = 0;
|
c.conformant = EDID_NOT_CONFORMANT;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* According to E-EDID (EDIDv1.3), has_name_descriptor and
|
* According to E-EDID (EDIDv1.3), has_name_descriptor and
|
||||||
|
@ -1516,7 +1517,7 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
|
||||||
* don't have them. As a workaround, we only print warning
|
* don't have them. As a workaround, we only print warning
|
||||||
* messages.
|
* messages.
|
||||||
*/
|
*/
|
||||||
if (!c.conformant)
|
if (c.conformant == EDID_NOT_CONFORMANT)
|
||||||
printk(BIOS_ERR,
|
printk(BIOS_ERR,
|
||||||
"EDID block does NOT conform to EDID 1.3!\n");
|
"EDID block does NOT conform to EDID 1.3!\n");
|
||||||
else if (!c.has_name_descriptor || !c.has_range_descriptor)
|
else if (!c.has_name_descriptor || !c.has_range_descriptor)
|
||||||
|
@ -1542,11 +1543,11 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
|
||||||
"\tDetailed block string not properly terminated\n");
|
"\tDetailed block string not properly terminated\n");
|
||||||
} else if (c.claims_one_point_two) {
|
} else if (c.claims_one_point_two) {
|
||||||
if (c.nonconformant_digital_display ||
|
if (c.nonconformant_digital_display ||
|
||||||
!c.has_valid_string_termination)
|
!c.has_valid_string_termination) {
|
||||||
c.conformant = 0;
|
c.conformant = EDID_NOT_CONFORMANT;
|
||||||
if (!c.conformant)
|
|
||||||
printk(BIOS_ERR,
|
printk(BIOS_ERR,
|
||||||
"EDID block does NOT conform to EDID 1.2!\n");
|
"EDID block does NOT conform to EDID 1.2!\n");
|
||||||
|
}
|
||||||
if (c.nonconformant_digital_display)
|
if (c.nonconformant_digital_display)
|
||||||
printk(BIOS_ERR,
|
printk(BIOS_ERR,
|
||||||
"\tDigital display field contains garbage: %x\n",
|
"\tDigital display field contains garbage: %x\n",
|
||||||
|
@ -1555,11 +1556,11 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
|
||||||
printk(BIOS_ERR,
|
printk(BIOS_ERR,
|
||||||
"\tDetailed block string not properly terminated\n");
|
"\tDetailed block string not properly terminated\n");
|
||||||
} else if (c.claims_one_point_oh) {
|
} else if (c.claims_one_point_oh) {
|
||||||
if (c.seen_non_detailed_descriptor)
|
if (c.seen_non_detailed_descriptor) {
|
||||||
c.conformant = 0;
|
c.conformant = EDID_NOT_CONFORMANT;
|
||||||
if (!c.conformant)
|
|
||||||
printk(BIOS_ERR,
|
printk(BIOS_ERR,
|
||||||
"EDID block does NOT conform to EDID 1.0!\n");
|
"EDID block does NOT conform to EDID 1.0!\n");
|
||||||
|
}
|
||||||
if (c.seen_non_detailed_descriptor)
|
if (c.seen_non_detailed_descriptor)
|
||||||
printk(BIOS_ERR,
|
printk(BIOS_ERR,
|
||||||
"\tHas descriptor blocks other than detailed timings\n");
|
"\tHas descriptor blocks other than detailed timings\n");
|
||||||
|
@ -1576,7 +1577,7 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
|
||||||
!c.has_valid_descriptor_ordering ||
|
!c.has_valid_descriptor_ordering ||
|
||||||
!c.has_valid_range_descriptor ||
|
!c.has_valid_range_descriptor ||
|
||||||
!c.manufacturer_name_well_formed) {
|
!c.manufacturer_name_well_formed) {
|
||||||
c.conformant = 0;
|
c.conformant = EDID_NOT_CONFORMANT;
|
||||||
printk(BIOS_ERR, "EDID block does not conform at all!\n");
|
printk(BIOS_ERR, "EDID block does not conform at all!\n");
|
||||||
if (c.nonconformant_extension)
|
if (c.nonconformant_extension)
|
||||||
printk(BIOS_ERR,
|
printk(BIOS_ERR,
|
||||||
|
@ -1618,7 +1619,7 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
|
||||||
if (c.warning_zero_preferred_refresh)
|
if (c.warning_zero_preferred_refresh)
|
||||||
printk(BIOS_ERR,
|
printk(BIOS_ERR,
|
||||||
"Warning: CVT block does not set preferred refresh rate\n");
|
"Warning: CVT block does not set preferred refresh rate\n");
|
||||||
return !c.conformant;
|
return c.conformant;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1322,7 +1322,7 @@ static void tegra_dp_update_config(struct tegra_dc_dp_data *dp,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decode_edid(buf, sizeof(buf), &edid)) {
|
if (decode_edid(buf, sizeof(buf), &edid) != EDID_CONFORMANT) {
|
||||||
printk(BIOS_ERR, "%s: Failed to decode EDID. Use defaults.\n",
|
printk(BIOS_ERR, "%s: Failed to decode EDID. Use defaults.\n",
|
||||||
__func__);
|
__func__);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1361,7 +1361,7 @@ static void tegra_dp_update_config(struct tegra_dc_dp_data *dp,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decode_edid(buf, sizeof(buf), &edid)) {
|
if (decode_edid(buf, sizeof(buf), &edid) != EDID_CONFORMANT) {
|
||||||
printk(BIOS_ERR, "%s: Failed to decode EDID. Use defaults.\n",
|
printk(BIOS_ERR, "%s: Failed to decode EDID. Use defaults.\n",
|
||||||
__func__);
|
__func__);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -778,7 +778,7 @@ static int rk_edp_read_edid(struct rk_edp *edp, struct edid *edid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decode_edid(buf, edid_size, edid)) {
|
if (decode_edid(buf, edid_size, edid) != EDID_CONFORMANT) {
|
||||||
printk(BIOS_ERR, "%s: Failed to decode EDID.\n",
|
printk(BIOS_ERR, "%s: Failed to decode EDID.\n",
|
||||||
__func__);
|
__func__);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -814,7 +814,7 @@ int rk_hdmi_get_edid(struct edid *edid)
|
||||||
|
|
||||||
/* Assume usage of HDMI implies an external display in which case
|
/* Assume usage of HDMI implies an external display in which case
|
||||||
* we should be lenient about errors that the EDID decoder finds. */
|
* we should be lenient about errors that the EDID decoder finds. */
|
||||||
if (decode_edid(edid_buf, edid_size, edid))
|
if (decode_edid(edid_buf, edid_size, edid) != EDID_CONFORMANT)
|
||||||
hdmi_debug("failed to decode edid.\n");
|
hdmi_debug("failed to decode edid.\n");
|
||||||
|
|
||||||
/* Try 480p for best compatibility. */
|
/* Try 480p for best compatibility. */
|
||||||
|
|
Loading…
Reference in New Issue