edid: Allow filtering out clocks in EDID; do it for rk3288 HDMI

Right now our EDID logic isn't very smart.  It always just picks the
first detailed mode and ignores the rest.  It's possible that this
detailed mode might be too fast for us, so let's allow some filtering.
We'll use this filtering to filter out modes > 165 MHz on the rk3288
HDMI port.

We choose 165 MHz for HDMI because this is the fasest you can go over
single link DVI.  We could try to be smart and allow faster speeds if we
detect that we're on HDMI, but this is unlikely to work anyway because >
165 MHz we start getting really jittery without a lot more work on HDMI
clocks.

This happens to make the HP ZR30w show the BIOS dev screen now.

BRANCH=none
BUG=chrome-os-partner:47008
TEST=HP ZR30w works

Change-Id: I1d20090b8ad84717ecc56a27ffe4ab0ee312628a
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/309568
Reviewed-by: David Hendricks <dhendrix@chromium.org>
This commit is contained in:
Douglas Anderson 2015-10-28 13:02:43 -07:00 committed by ChromeOS bot
commit 89b81d47f1
8 changed files with 17 additions and 8 deletions

View file

@ -95,7 +95,7 @@ struct edid {
};
/* 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, int max_khz);
void set_vbe_mode_info_valid(struct edid *edid, uintptr_t fb_addr);
int set_display_mode(struct edid *edid, enum edid_modes mode);

View file

@ -67,6 +67,7 @@ struct edid_context {
int warning_excessive_dotclock_correction;
int warning_zero_preferred_refresh;
int conformant;
int max_khz;
};
/* Stuff that isn't used anywhere but is nice to pretty-print while
@ -545,6 +546,11 @@ detailed_block(struct edid *result_edid, unsigned char *x, int in_extension,
extra_info.syncmethod, x[17] & 0x80 ?" interlaced" : "",
extra_info.stereo);
if (c->max_khz && out->mode.pixel_clock > c->max_khz) {
printk(BIOS_SPEW, "Skipping %d\n", out->mode.pixel_clock);
return 1;
}
if (! c->did_detailed_timing) {
printk(BIOS_SPEW, "Did detailed timing\n");
c->did_detailed_timing = 1;
@ -1041,8 +1047,10 @@ int set_display_mode(struct edid *edid, enum edid_modes mode)
* required to be 128 bytes long, per the standard,
* but we have no way of checking this minimum length.
* We accept what we are given.
*
* We'll filter out modes > max_khz; 0 for no filter
*/
int decode_edid(unsigned char *edid, int size, struct edid *out)
int decode_edid(unsigned char *edid, int size, struct edid *out, int max_khz)
{
int analog, i, j;
struct edid_context c = {
@ -1055,6 +1063,7 @@ int decode_edid(unsigned char *edid, int size, struct edid *out)
.has_valid_max_dotclock = 1,
.has_valid_string_termination = 1,
.conformant = 1,
.max_khz = max_khz,
};
dump_breakdown(edid);

View file

@ -227,7 +227,7 @@ int panel_lightup(struct intel_dp *dp, unsigned int init_fb)
dp->edidlen++;
}
edid_ok = decode_edid(dp->rawedid, dp->edidlen, &dp->edid);
edid_ok = decode_edid(dp->rawedid, dp->edidlen, &dp->edid, 0);
printk(BIOS_SPEW, "decode edid returns %d\n", edid_ok);
compute_display_params(dp);

View file

@ -259,7 +259,7 @@ int i915lightup(unsigned int pphysbase, unsigned int piobase,
edid_ok = decode_edid((unsigned char *)&link_edid_data,
sizeof(link_edid_data), &edid);
sizeof(link_edid_data), &edid, 0);
printk(BIOS_SPEW, "decode edid returns %d\n", edid_ok);
edid.framebuffer_bits_per_pixel = 32;

View file

@ -242,7 +242,7 @@ int panel_lightup(struct intel_dp *dp, unsigned int init_fb)
dp->edidlen++;
}
edid_ok = decode_edid(dp->rawedid, dp->edidlen, &dp->edid);
edid_ok = decode_edid(dp->rawedid, dp->edidlen, &dp->edid, 0);
printk(BIOS_SPEW, "decode edid returns %d\n", edid_ok);

View file

@ -1322,7 +1322,7 @@ static void tegra_dp_update_config(struct tegra_dc_dp_data *dp,
return;
}
if (decode_edid(buf, sizeof(buf), &edid)) {
if (decode_edid(buf, sizeof(buf), &edid, 0)) {
printk(BIOS_ERR, "%s: Failed to decode EDID. Use defaults.\n",
__func__);
return;

View file

@ -789,7 +789,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, 0)) {
printk(BIOS_ERR, "%s: Failed to decode EDID.\n",
__func__);
return -1;

View file

@ -805,7 +805,7 @@ int rk_hdmi_get_edid(struct edid *edid)
/* Assume usage of HDMI implies an external display in which case
* 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, 165000))
hdmi_debug("failed to decode edid.\n");
/* Try 480p for best compatibility. */