Received: by 2002:a25:ad19:0:0:0:0:0 with SMTP id y25csp10751248ybi; Thu, 25 Jul 2019 04:43:08 -0700 (PDT) X-Google-Smtp-Source: APXvYqzFg4zn1F+WDS+FjzhaN8Qy7wMa+S9ZPJ60RrifJLuEQfmCyQdfnJCG4weckJYOcon11DrZ X-Received: by 2002:a17:90a:9a95:: with SMTP id e21mr33151000pjp.98.1564054988745; Thu, 25 Jul 2019 04:43:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1564054988; cv=none; d=google.com; s=arc-20160816; b=to0e+kt/uIM4/f/pS7OJY+smpwwMo8yhBSKxDcNP4g7IeR286riedvYy6hOVpjdhHo wUPdzs6eaXMqk2LBpcpRcjtxa3xlWjgpUfVTbsSws1wZVVYHx4UqbIEpYk6zZkTzUAA1 ngjypR2qw4nFWCh1/EczFA5Y7X7/q3e8HKjjAz7KKug9MAkL38rkFNC85NDCHl4xjvMX bhXyCu1TqeLzgOUMiV0MXzd3Zmb4eccSB89Hc85AMF8GYbIWGqzeODVrqrP0/S0BK09T 26Ea5k7KSIrv1dG3Yyv2L7DjG3JvGLRjMpfCCovOCggZI3ZLPuT1z0lwtsiXnc0SWOrx 1gRw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=rjmafxlsEVs96RScDky+FUMOYMz6XG84aUvZBy3UToU=; b=EX2gn9lfmsYU9jRRrQfcDc+aEiTWJYwNGTo4OgR3mivDe/6zNJe/R8zHoUAHNo4ylB 2aPEg+9LphdTt199No5HmD6QyfY2Xpi3rT4/AQvGFKG1HCLJfjGQ1fwC2BVjrBbApkCQ mDtLpBtKpIfm+Fu0iSOMGo/3eKoKaFMLGCED4gVjBaQvxtPt/fvmKHxJbN1ljl0r6pJI RN6fAl8AdfdQOWFmFgQtg4kx72QSDyed67HZ3CdvdgyCxPtFcJ/xXmji1S1ELzND4WC0 SQzznJAWz2zjYeSnTGQ2ApY8fBLkhNa8S9zgvQt8/f0T3ED6y08y8x1xv9bfIUqkBx4K aC1g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=bwBlThUx; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t15si16567017plo.360.2019.07.25.04.42.20; Thu, 25 Jul 2019 04:43:08 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=bwBlThUx; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391269AbfGYFox (ORCPT + 99 others); Thu, 25 Jul 2019 01:44:53 -0400 Received: from mail.kernel.org ([198.145.29.99]:60094 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2405043AbfGYFos (ORCPT ); Thu, 25 Jul 2019 01:44:48 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id D9E5222BF3; Thu, 25 Jul 2019 05:44:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1564033488; bh=kemwoSLmNEHvI4VS81nISKMTP/n8RzGnhLgo27332Ao=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bwBlThUxS7e7+qGfRvFQeZMkeRzeoPeZppD4PQnYvwDq01KBx3fo+m2mJDEaQrJ42 zeBBJfAKbo1bz8Opvlk5qFhbY3XldN7IeootE5ieH0tKOMOd5zg1f1l5Mddc2zc9bC v4CbMEIU3vPOjZEUP/s/6Od4Rde2XqYOIDyjGZbw= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Andres Rodriguez , Dave Airlie , Jani Nikula Subject: [PATCH 4.19 227/271] drm/edid: parse CEA blocks embedded in DisplayID Date: Wed, 24 Jul 2019 21:21:36 +0200 Message-Id: <20190724191714.611888529@linuxfoundation.org> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20190724191655.268628197@linuxfoundation.org> References: <20190724191655.268628197@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Andres Rodriguez commit e28ad544f462231d3fd081a7316339359efbb481 upstream. DisplayID blocks allow embedding of CEA blocks. The payloads are identical to traditional top level CEA extension blocks, but the header is slightly different. This change allows the CEA parser to find a CEA block inside a DisplayID block. Additionally, it adds support for parsing the embedded CTA header. No further changes are necessary due to payload parity. This change fixes audio support for the Valve Index HMD. Signed-off-by: Andres Rodriguez Reviewed-by: Dave Airlie Cc: Jani Nikula Cc: # v4.15 Signed-off-by: Dave Airlie Link: https://patchwork.freedesktop.org/patch/msgid/20190619180901.17901-1-andresx7@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_edid.c | 81 ++++++++++++++++++++++++++++++++++++++------ include/drm/drm_displayid.h | 10 +++++ 2 files changed, 80 insertions(+), 11 deletions(-) --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1349,6 +1349,7 @@ MODULE_PARM_DESC(edid_fixup, static void drm_get_displayid(struct drm_connector *connector, struct edid *edid); +static int validate_displayid(u8 *displayid, int length, int idx); static int drm_edid_block_checksum(const u8 *raw_edid) { @@ -2932,16 +2933,46 @@ static u8 *drm_find_edid_extension(const return edid_ext; } -static u8 *drm_find_cea_extension(const struct edid *edid) -{ - return drm_find_edid_extension(edid, CEA_EXT); -} static u8 *drm_find_displayid_extension(const struct edid *edid) { return drm_find_edid_extension(edid, DISPLAYID_EXT); } +static u8 *drm_find_cea_extension(const struct edid *edid) +{ + int ret; + int idx = 1; + int length = EDID_LENGTH; + struct displayid_block *block; + u8 *cea; + u8 *displayid; + + /* Look for a top level CEA extension block */ + cea = drm_find_edid_extension(edid, CEA_EXT); + if (cea) + return cea; + + /* CEA blocks can also be found embedded in a DisplayID block */ + displayid = drm_find_displayid_extension(edid); + if (!displayid) + return NULL; + + ret = validate_displayid(displayid, length, idx); + if (ret) + return NULL; + + idx += sizeof(struct displayid_hdr); + for_each_displayid_db(displayid, block, idx, length) { + if (block->tag == DATA_BLOCK_CTA) { + cea = (u8 *)block; + break; + } + } + + return cea; +} + /* * Calculate the alternate clock for the CEA mode * (60Hz vs. 59.94Hz etc.) @@ -3665,13 +3696,38 @@ cea_revision(const u8 *cea) static int cea_db_offsets(const u8 *cea, int *start, int *end) { - /* Data block offset in CEA extension block */ - *start = 4; - *end = cea[2]; - if (*end == 0) - *end = 127; - if (*end < 4 || *end > 127) - return -ERANGE; + /* DisplayID CTA extension blocks and top-level CEA EDID + * block header definitions differ in the following bytes: + * 1) Byte 2 of the header specifies length differently, + * 2) Byte 3 is only present in the CEA top level block. + * + * The different definitions for byte 2 follow. + * + * DisplayID CTA extension block defines byte 2 as: + * Number of payload bytes + * + * CEA EDID block defines byte 2 as: + * Byte number (decimal) within this block where the 18-byte + * DTDs begin. If no non-DTD data is present in this extension + * block, the value should be set to 04h (the byte after next). + * If set to 00h, there are no DTDs present in this block and + * no non-DTD data. + */ + if (cea[0] == DATA_BLOCK_CTA) { + *start = 3; + *end = *start + cea[2]; + } else if (cea[0] == CEA_EXT) { + /* Data block offset in CEA extension block */ + *start = 4; + *end = cea[2]; + if (*end == 0) + *end = 127; + if (*end < 4 || *end > 127) + return -ERANGE; + } else { + return -ENOTSUPP; + } + return 0; } @@ -5218,6 +5274,9 @@ static int drm_parse_display_id(struct d case DATA_BLOCK_TYPE_1_DETAILED_TIMING: /* handled in mode gathering code. */ break; + case DATA_BLOCK_CTA: + /* handled in the cea parser code. */ + break; default: DRM_DEBUG_KMS("found DisplayID tag 0x%x, unhandled\n", block->tag); break; --- a/include/drm/drm_displayid.h +++ b/include/drm/drm_displayid.h @@ -40,6 +40,7 @@ #define DATA_BLOCK_DISPLAY_INTERFACE 0x0f #define DATA_BLOCK_STEREO_DISPLAY_INTERFACE 0x10 #define DATA_BLOCK_TILED_DISPLAY 0x12 +#define DATA_BLOCK_CTA 0x81 #define DATA_BLOCK_VENDOR_SPECIFIC 0x7f @@ -90,4 +91,13 @@ struct displayid_detailed_timing_block { struct displayid_block base; struct displayid_detailed_timings_1 timings[0]; }; + +#define for_each_displayid_db(displayid, block, idx, length) \ + for ((block) = (struct displayid_block *)&(displayid)[idx]; \ + (idx) + sizeof(struct displayid_block) <= (length) && \ + (idx) + sizeof(struct displayid_block) + (block)->num_bytes <= (length) && \ + (block)->num_bytes > 0; \ + (idx) += (block)->num_bytes + sizeof(struct displayid_block), \ + (block) = (struct displayid_block *)&(displayid)[idx]) + #endif