Received: by 2002:a05:6a10:1d13:0:0:0:0 with SMTP id pp19csp1030279pxb; Wed, 1 Sep 2021 15:45:50 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxP9o7pcXqlVBEoEA3NQ84bn4Aphi1xEGWALDhkwBKOnM3CU6NZeqNYvaM4MnWAnVdKnPaX X-Received: by 2002:a17:906:9388:: with SMTP id l8mr176749ejx.307.1630536350387; Wed, 01 Sep 2021 15:45:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1630536350; cv=none; d=google.com; s=arc-20160816; b=axiCzne2Lupenc4lmJhZ0UnMlJYwwGq63Y2Uqf451RBtqxoOx819yC109ao3nn5KLN 4VUYnza+DhuWYMuYPIVazZBkVNtch2UiYl698xpSoqyxaFueHKMykI/NAcrHgpI6Zm1a N8Dl17Z2oBFtOEENdOt+HLsApYZrpK4ScuVo46r+b9md/Y3QBLojMLZz1Mpt0Du5yQwK uwiPoci98UkL+XdWAXkxpm9Merk8ZUpNr6tbITXhoC9W9foFhJxoaVYAVfcf6jIErqqr yfwGUJ3mvPBzEwWGhLXgmc5duuhk809xSE6CDc7HCIA/NtIcfz5VfIJs+soHWgnr8M+R P8kA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=NFnoIbGurLHygQYzR/1vkknC/vUF1WONmleiQRHkl10=; b=r9OuChRBr8aI3LN/C8yJzCGcwBbGw5bNZxwOEYUGZouhjObURS1GUqfuDbEC7ax+kV RK2F0Uc1f4qlaIukdxJ/hdLleI0UpgKd4iEN7kvXpRx0AIuSYsJlxTtDO6Fg8iW4o/gX OR2wcslw5IAlUIf5iGfRcTgF+otV5mfSq1rhkTdhJclMHMBVFgO8aH1NTe+tiEXXpnCx Sv14orhFGTkSi+dPl8R8zR6/ExLM0bkF/bQqV76YnHZfUwpduI+BOJWSsnrTvz1yiq6n GMIMhwqUQq2l/zEBr6y8qDbhbkxH5TLVIQH3gXsapsR78I+0ufEqW4xlLJFdT86RQJBd fm9A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=d5lm75+R; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id w4si112990edx.403.2021.09.01.15.45.26; Wed, 01 Sep 2021 15:45:50 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=d5lm75+R; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344200AbhIAUVp (ORCPT + 99 others); Wed, 1 Sep 2021 16:21:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55266 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245279AbhIAUVd (ORCPT ); Wed, 1 Sep 2021 16:21:33 -0400 Received: from mail-pl1-x633.google.com (mail-pl1-x633.google.com [IPv6:2607:f8b0:4864:20::633]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 07E9EC0612E7 for ; Wed, 1 Sep 2021 13:20:32 -0700 (PDT) Received: by mail-pl1-x633.google.com with SMTP id n4so366191plh.9 for ; Wed, 01 Sep 2021 13:20:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=NFnoIbGurLHygQYzR/1vkknC/vUF1WONmleiQRHkl10=; b=d5lm75+RLct6X/Jl04wCP559lXGWD7QrbiXaXZsBpu0T/HPKljNQr18x6eRHAPB/Uv A6MK+U8iAPjyDVn9LejUQEv7cJDRahTvyejMAVtMF5Rf1AiBO8Rih3QARced7J00qOhd gvUqgtvGrIcE//kMcXNfoL+wYIvMqL3MBTWUw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=NFnoIbGurLHygQYzR/1vkknC/vUF1WONmleiQRHkl10=; b=eoSR+RcXtsDbqsCxue7hbaQrvV7/cmiTg0BhYXVoVqeWGki89SL2OIaxz4MXyqSnTT WceZueqFzGazaQBy5l67rONi2YDxT5EN+5lnl+bdYVnUErVsez0IuDGNty0tcWSBvTWb avpnKV8job0QS1m13AsqovasbRyDaUUxTmsxEWjwAlBSxeyNw1NF6SzbnWpRgAG7nR3y ZNgM+/l9SjZ7+2n0I+1kZzI/SBCecJoyuwfluUS4meI97lUdYWQC98kNNRK9XonPqMWp qaViGy91r8YlL4YBJn8shi6kcnzl1RB9UDTDBv5ywH1fAC1o14jhg0dkxTvEetL3wrKw TlcA== X-Gm-Message-State: AOAM533Dzb6yjAL+AGY4Y/8KuD32K24UeejJgaRUl+Ei41DJJYU4BN/Q THOuEMEXLxPWvC1fwf8gIMgoog== X-Received: by 2002:a17:90b:128a:: with SMTP id fw10mr1225651pjb.212.1630527631467; Wed, 01 Sep 2021 13:20:31 -0700 (PDT) Received: from tictac2.mtv.corp.google.com ([2620:15c:202:201:958b:b561:a735:e774]) by smtp.gmail.com with ESMTPSA id x15sm321178pfq.31.2021.09.01.13.20.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Sep 2021 13:20:31 -0700 (PDT) From: Douglas Anderson To: Thierry Reding , Rob Herring , Sam Ravnborg Cc: Maarten Lankhorst , linux-arm-msm@vger.kernel.org, Bjorn Andersson , Linus W , Daniel Vetter , devicetree@vger.kernel.org, Steev Klimaszewski , Thomas Zimmermann , Maxime Ripard , David Airlie , dri-devel@lists.freedesktop.org, Douglas Anderson , linux-kernel@vger.kernel.org Subject: [PATCH v3 03/16] drm/edid: Allow the querying/working with the panel ID from the EDID Date: Wed, 1 Sep 2021 13:19:21 -0700 Message-Id: <20210901131531.v3.3.I4a672175ba1894294d91d3dbd51da11a8239cf4a@changeid> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog In-Reply-To: <20210901201934.1084250-1-dianders@chromium.org> References: <20210901201934.1084250-1-dianders@chromium.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org EDIDs have 32-bits worth of data which is intended to be used to uniquely identify the make/model of a panel. This has historically been used only internally in the EDID processing code to identify quirks with panels. We'd like to use this panel ID in panel-simple to identify which panel is hooked up and from that information figure out power sequence timings. Let's expose this information from the EDID code and also allow it to be accessed early, before a connector has been created. To make matching in the panel-simple code easier, we'll return the panel ID as a 32-bit value. We'll provide some functions for converting this value back and forth to something more human readable. Signed-off-by: Douglas Anderson --- Changes in v3: - Decode hex product ID w/ same endianness as everyone else. drivers/gpu/drm/drm_edid.c | 59 ++++++++++++++++++++++++++++++++++++++ include/drm/drm_edid.h | 47 ++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index a22c38482a90..ac128bc3478a 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2086,6 +2086,65 @@ struct edid *drm_get_edid(struct drm_connector *connector, } EXPORT_SYMBOL(drm_get_edid); +/** + * drm_get_panel_id - Get a panel's ID through DDC + * @adapter: I2C adapter to use for DDC + * + * This function reads the first block of the EDID of a panel and (assuming + * that the EDID is valid) extracts the ID out of it. The ID is a 32-bit value + * (16 bits of manufacturer ID and 16 bits of per-manufacturer ID) that's + * supposed to be different for each different modem of panel. + * + * This function is intended to be used during early probing on devices where + * more than one panel might be present. Because of its intended use it must + * assume that the EDID of the panel is correct, at least as far as the ID + * is concerned (in other words, we don't process any overrides here). + * + * NOTE: it's expected that this function and drm_do_get_edid() will both + * be read the EDID, but there is no caching between them. Since we're only + * reading the first block, hopefully this extra overhead won't be too big. + * + * Return: A 32-bit ID that should be different for each make/model of panel. + * See the functions encode_edid_id() and decode_edid_id() for some + * details on the structure of this ID. + */ +u32 drm_get_panel_id(struct i2c_adapter *adapter) +{ + struct edid *edid; + u32 val; + + edid = drm_do_get_edid_blk0(drm_do_probe_ddc_edid, adapter, NULL, NULL); + + /* + * There are no manufacturer IDs of 0, so if there is a problem reading + * the EDID then we'll just return 0. + */ + if (IS_ERR_OR_NULL(edid)) + return 0; + + /* + * In theory we could try to de-obfuscate this like edid_get_quirks() + * does, but it's easier to just deal with a 32-bit number. + * + * NOTE that we deal with endianness differently for the top half + * of this ID than for the bottom half. The bottom half (the product + * id) gets decoded as little endian by the EDID_PRODUCT_ID because + * that's how everyone seems to interpret it. The top half (the mfg_id) + * gets stored as big endian because that makes encode_edid_id() and + * decode_edid_id() easier to write (it's easier to extract the ASCII). + * It doesn't really matter, though, as long as the number here is + * unique. + */ + val = (u32)edid->mfg_id[0] << 24 | + (u32)edid->mfg_id[1] << 16 | + (u32)EDID_PRODUCT_ID(edid); + + kfree(edid); + + return val; +} +EXPORT_SYMBOL(drm_get_panel_id); + /** * drm_get_edid_switcheroo - get EDID data for a vga_switcheroo output * @connector: connector we're probing diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index deccfd39e6db..73da40d0b5d1 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -508,6 +508,52 @@ static inline u8 drm_eld_get_conn_type(const uint8_t *eld) return eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_CONN_TYPE_MASK; } +/** + * encode_edid_id - Encode an ID for matching against drm_get_panel_id() + * @vend_chr_0: First character of the vendor string. + * @vend_chr_2: Second character of the vendor string. + * @vend_chr_3: Third character of the vendor string. + * @product_id: The 16-bit product ID. + * + * This is a macro so that it can be calculated at compile time and used + * as an initializer. + * + * For instance: + * encode_edid_id('B', 'O', 'E', 0x2d08) => 0x09e52d08 + * + * Return: a 32-bit ID per panel. + */ +#define encode_edid_id(vend_chr_0, vend_chr_1, vend_chr_2, product_id) \ + ((((u32)(vend_chr_0) - '@') & 0x1f) << 26 | \ + (((u32)(vend_chr_1) - '@') & 0x1f) << 21 | \ + (((u32)(vend_chr_2) - '@') & 0x1f) << 16 | \ + ((product_id) & 0xffff)) + +/** + * decode_edid_id - Decode a panel ID from encode_edid_id() + * @panel_id: The panel ID to decode. + * @vend: A 4-byte buffer to store the 3-letter vendor string plus a '\0' + * termination + * @product_id: The product ID will be returned here. + * + * For instance, after: + * decode_edid_id(0x09e52d08, vend, &product_id) + * These will be true: + * vend[0] = 'B' + * vend[1] = 'O' + * vend[2] = 'E' + * vend[3] = '\0' + * product_id = 0x2d08 + */ +static inline void decode_edid_id(u32 panel_id, char vend[4], u16 *product_id) +{ + *product_id = (u16)(panel_id & 0xffff); + vend[0] = '@' + ((panel_id >> 26) & 0x1f); + vend[1] = '@' + ((panel_id >> 21) & 0x1f); + vend[2] = '@' + ((panel_id >> 16) & 0x1f); + vend[3] = '\0'; +} + bool drm_probe_ddc(struct i2c_adapter *adapter); struct edid *drm_do_get_edid(struct drm_connector *connector, int (*get_edid_block)(void *data, u8 *buf, unsigned int block, @@ -515,6 +561,7 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, void *data); struct edid *drm_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter); +u32 drm_get_panel_id(struct i2c_adapter *adapter); struct edid *drm_get_edid_switcheroo(struct drm_connector *connector, struct i2c_adapter *adapter); struct edid *drm_edid_duplicate(const struct edid *edid); -- 2.33.0.259.gc128427fd7-goog