From patchwork Tue Dec 2 00:48:46 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 416653 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id D413F140284 for ; Tue, 2 Dec 2014 11:49:35 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 5BB344B78E; Tue, 2 Dec 2014 01:49:31 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id tB1RueJGUocf; Tue, 2 Dec 2014 01:49:31 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id CA1184B794; Tue, 2 Dec 2014 01:49:30 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B553C4B714 for ; Tue, 2 Dec 2014 01:49:22 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id DV9XsVIhiewU for ; Tue, 2 Dec 2014 01:49:22 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-yk0-f202.google.com (mail-yk0-f202.google.com [209.85.160.202]) by theia.denx.de (Postfix) with ESMTPS id 623684B721 for ; Tue, 2 Dec 2014 01:49:19 +0100 (CET) Received: by mail-yk0-f202.google.com with SMTP id 9so620164ykp.3 for ; Mon, 01 Dec 2014 16:49:18 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Iv9sT0YoOSfH2LQW5XewEXHjeCHw6aXT7ipOc31c0tw=; b=aFQssvY+Yn0kZpCBbgcmIpUJXIZDxoIN0NViRMFucuh5sz/IWZmvANdhokx0DAG0rj cZtv1cznF7/lv3ldWpcznFGlPZlr2pWjTp8B0C/P1vSdgkNAPayR+sgb8f2oMddUlnbO nOeKMuVVnGaCfZsSf704U1nVFhQqMGMO7fS5Uf+Jk7Q+aJNWcQ6aj7/VJcs8JqacEUPN Tb7YwXHNBxjCUoyXxOl0wET9IW4Y2RvdqqZXLDxoETNZJkBa7KlI3DxDRqgDpEiw8v/a B4YoAXxuobK6SkoJKJ1XU726A7oRn82Tu4wZrz4oVIzn2LRL4ihr9YxZlRxyrcBhevpd Rcfw== X-Gm-Message-State: ALoCoQmKU102a9y7dra5GeFG7Ibao/MtaIxtdOJHJ+r4J8bJLkq2ZmlaFmcJVG1+mOGQtuoeiu7g X-Received: by 10.236.61.132 with SMTP id w4mr59957126yhc.2.1417481358711; Mon, 01 Dec 2014 16:49:18 -0800 (PST) Received: from corpmail-nozzle1-2.hot.corp.google.com ([100.108.1.103]) by gmr-mx.google.com with ESMTPS id 5si771799yhd.6.2014.12.01.16.49.18 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 01 Dec 2014 16:49:18 -0800 (PST) Received: from kaki.bld.corp.google.com ([172.29.216.32]) by corpmail-nozzle1-2.hot.corp.google.com with ESMTP id auXTZ6OS.2; Mon, 01 Dec 2014 16:49:18 -0800 Received: by kaki.bld.corp.google.com (Postfix, from userid 121222) id 04D162210FD; Mon, 1 Dec 2014 17:49:17 -0700 (MST) From: Simon Glass To: U-Boot Mailing List Date: Mon, 1 Dec 2014 17:48:46 -0700 Message-Id: <1417481333-30526-19-git-send-email-sjg@chromium.org> X-Mailer: git-send-email 2.2.0.rc0.207.ga3a616c In-Reply-To: <1417481333-30526-1-git-send-email-sjg@chromium.org> References: <1417481333-30526-1-git-send-email-sjg@chromium.org> Cc: Stephen Warren , Tom Warren Subject: [U-Boot] [PATCH 18/25] edid: Add a function to read detailed monitor timings X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.13 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de For digital displays (such as EDP LCDs) we would like to read the EDID information and use that to set display timings. Provide a function to do this. Signed-off-by: Simon Glass --- common/edid.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/edid.h | 19 +++++++++++ 2 files changed, 125 insertions(+) diff --git a/common/edid.c b/common/edid.c index e66108f..c031eee 100644 --- a/common/edid.c +++ b/common/edid.c @@ -12,6 +12,8 @@ #include #include +#include +#include #include #include @@ -53,6 +55,110 @@ int edid_get_ranges(struct edid1_info *edid, unsigned int *hmin, return -1; } +/* Set all parts of a timing entry to the same value */ +static void set_entry(struct timing_entry *entry, u32 value) +{ + entry->min = value; + entry->typ = value; + entry->max = value; +} + +/** + * decode_timing() - Decoding an 18-byte detailed timing record + * + * @buf: Pointer to EDID detailed timing record + * @timing: Place to put timing + */ +static void decode_timing(u8 *buf, struct display_timing *timing) +{ + uint x_mm, y_mm; + unsigned int ha, hbl, hso, hspw, hborder; + unsigned int va, vbl, vso, vspw, vborder; + + /* Edid contains pixel clock in terms of 10KHz */ + set_entry(&timing->pixelclock, (buf[0] + (buf[1] << 8)) * 10000); + x_mm = (buf[12] + ((buf[14] & 0xf0) << 4)); + y_mm = (buf[13] + ((buf[14] & 0x0f) << 8)); + ha = (buf[2] + ((buf[4] & 0xf0) << 4)); + hbl = (buf[3] + ((buf[4] & 0x0f) << 8)); + hso = (buf[8] + ((buf[11] & 0xc0) << 2)); + hspw = (buf[9] + ((buf[11] & 0x30) << 4)); + hborder = buf[15]; + va = (buf[5] + ((buf[7] & 0xf0) << 4)); + vbl = (buf[6] + ((buf[7] & 0x0f) << 8)); + vso = ((buf[10] >> 4) + ((buf[11] & 0x0c) << 2)); + vspw = ((buf[10] & 0x0f) + ((buf[11] & 0x03) << 4)); + vborder = buf[16]; + + set_entry(&timing->hactive, ha); + set_entry(&timing->hfront_porch, hso); + set_entry(&timing->hback_porch, hbl - hso - hspw); + set_entry(&timing->hsync_len, hspw); + + set_entry(&timing->vactive, va); + set_entry(&timing->vfront_porch, vso); + set_entry(&timing->vback_porch, vbl - vso - vspw); + set_entry(&timing->vsync_len, vspw); + + debug("Detailed mode clock %u Hz, %d mm x %d mm\n" + " %04x %04x %04x %04x hborder %x\n" + " %04x %04x %04x %04x vborder %x\n", + timing->pixelclock.typ, + x_mm, y_mm, + ha, ha + hso, ha + hso + hspw, + ha + hbl, hborder, + va, va + vso, va + vso + vspw, + va + vbl, vborder); +} + +int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing, + int *panel_bits_per_colourp) +{ + struct edid1_info *edid = (struct edid1_info *)buf; + bool timing_done; + int i; + + if (buf_size < sizeof(*edid) || edid_check_info(edid)) { + debug("%s: Invalid buffer\n", __func__); + return -EINVAL; + } + + if (!EDID1_INFO_FEATURE_PREFERRED_TIMING_MODE(*edid)) { + debug("%s: No preferred timing\n", __func__); + return -ENOENT; + } + + /* Look for detailed timing */ + timing_done = false; + for (i = 0; i < 4; i++) { + struct edid_monitor_descriptor *desc; + + desc = &edid->monitor_details.descriptor[i]; + if (desc->zero_flag_1 != 0) { + decode_timing((u8 *)desc, timing); + timing_done = true; + break; + } + } + if (!timing_done) + return -EINVAL; + + if (!EDID1_INFO_VIDEO_INPUT_DIGITAL(*edid)) { + debug("%s: Not a digital display\n", __func__); + return -ENOSYS; + } + if (edid->version != 1 || edid->revision < 4) { + debug("%s: EDID version %d.%d does not have required info\n", + __func__, edid->version, edid->revision); + *panel_bits_per_colourp = -1; + } else { + *panel_bits_per_colourp = + ((edid->video_input_definition & 0x70) >> 3) + 4; + } + + return 0; +} + /** * Snip the tailing whitespace/return of a string. * diff --git a/include/edid.h b/include/edid.h index 480a773..d331738 100644 --- a/include/edid.h +++ b/include/edid.h @@ -15,6 +15,9 @@ #include +/* Size of the EDID data */ +#define EDID_SIZE 128 + #define GET_BIT(_x, _pos) \ (((_x) >> (_pos)) & 1) #define GET_BITS(_x, _pos_msb, _pos_lsb) \ @@ -255,4 +258,20 @@ int edid_get_ranges(struct edid1_info *edid, unsigned int *hmin, unsigned int *hmax, unsigned int *vmin, unsigned int *vmax); +struct display_timing; + +/** + * edid_get_timing() - Get basic digital display parameters + * + * @param buf Buffer containing EDID data + * @param buf_size Size of buffer in bytes + * @param timing Place to put preferring timing information + * @param panel_bits_per_colourp Place to put the number of bits per + * colour supported by the panel. This will be set to + * -1 if not available + * @return 0 if timings are OK, -ve on error + */ +int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing, + int *panel_bits_per_colourp); + #endif /* __EDID_H_ */