From 89b81d47f10444a50205e5df0c3a1a523e7a7aa9 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Wed, 28 Oct 2015 13:02:43 -0700 Subject: [PATCH] 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 Reviewed-on: https://chromium-review.googlesource.com/309568 Reviewed-by: David Hendricks --- src/include/edid.h | 2 +- src/lib/edid.c | 11 ++++++++++- src/mainboard/google/falco/gma.c | 2 +- src/mainboard/google/link/i915.c | 2 +- src/mainboard/google/peppy/gma.c | 2 +- src/soc/nvidia/tegra124/dp.c | 2 +- src/soc/rockchip/rk3288/edp.c | 2 +- src/soc/rockchip/rk3288/hdmi.c | 2 +- 8 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/include/edid.h b/src/include/edid.h index 924f0f2d1c..f013832d6a 100644 --- a/src/include/edid.h +++ b/src/include/edid.h @@ -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); diff --git a/src/lib/edid.c b/src/lib/edid.c index 22c342e8aa..910a990a8d 100644 --- a/src/lib/edid.c +++ b/src/lib/edid.c @@ -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); diff --git a/src/mainboard/google/falco/gma.c b/src/mainboard/google/falco/gma.c index ec26e4418d..8e47ed6d00 100644 --- a/src/mainboard/google/falco/gma.c +++ b/src/mainboard/google/falco/gma.c @@ -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); diff --git a/src/mainboard/google/link/i915.c b/src/mainboard/google/link/i915.c index 042cd80f1d..c06f19f27d 100644 --- a/src/mainboard/google/link/i915.c +++ b/src/mainboard/google/link/i915.c @@ -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; diff --git a/src/mainboard/google/peppy/gma.c b/src/mainboard/google/peppy/gma.c index 189da7e9ee..c86f9de0d8 100644 --- a/src/mainboard/google/peppy/gma.c +++ b/src/mainboard/google/peppy/gma.c @@ -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); diff --git a/src/soc/nvidia/tegra124/dp.c b/src/soc/nvidia/tegra124/dp.c index 3a3bce8b15..1e125f6ad0 100644 --- a/src/soc/nvidia/tegra124/dp.c +++ b/src/soc/nvidia/tegra124/dp.c @@ -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; diff --git a/src/soc/rockchip/rk3288/edp.c b/src/soc/rockchip/rk3288/edp.c index 3f27195199..0636cf2f35 100644 --- a/src/soc/rockchip/rk3288/edp.c +++ b/src/soc/rockchip/rk3288/edp.c @@ -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; diff --git a/src/soc/rockchip/rk3288/hdmi.c b/src/soc/rockchip/rk3288/hdmi.c index 388a9cfa41..6820d8cac4 100644 --- a/src/soc/rockchip/rk3288/hdmi.c +++ b/src/soc/rockchip/rk3288/hdmi.c @@ -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. */