From patchwork Fri Jul 30 21:26:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 489910 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.5 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 50E75C4320A for ; Fri, 30 Jul 2021 21:26:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 36B7960FE7 for ; Fri, 30 Jul 2021 21:26:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231276AbhG3V0y (ORCPT ); Fri, 30 Jul 2021 17:26:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35070 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231865AbhG3V0w (ORCPT ); Fri, 30 Jul 2021 17:26:52 -0400 Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A926FC061765 for ; Fri, 30 Jul 2021 14:26:46 -0700 (PDT) Received: by mail-pl1-x631.google.com with SMTP id e21so12620447pla.5 for ; Fri, 30 Jul 2021 14:26:46 -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=uDbg21Rf2V3jdZDSKF8dbOSamKttBFrGYQS/hOkLKIM=; b=Dt3QaGEKJYQZpLNZ++o1Zh7kagDav2QSU5ZW7Z46Hb/uObkC78VphH8EgnIIj97Rdm 1EO47fO8lBpdVGkPx0g2fBeXbz25u3zHUp/jrnZB3stIlEmHpihzNztapECzMg7HLXKw AmWLluiT4t/pxEPrj5pbfoOpqwWsk1W+n4O/w= 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=uDbg21Rf2V3jdZDSKF8dbOSamKttBFrGYQS/hOkLKIM=; b=QtbwhQYhLhOkhALie6+nRM9w13xTGD68MiP/DUeHhuOyoM1vgR3WRULeD0OElwrHA4 VhCnihxWfwxQF/bDIaarm7PW9cUTdsyWwj0j3cK0FVWAdIX/JlComLjdHKCEqXB5xfme 8nG/ltakJO0oNVK+42bTf+IWVMytCOjMMT95ciN+ffqh50Nbh73wwanibeywwx3lZL4i iJ8pmcdtapYeagbsz0SV+cJmgNLJ/zpD2l08BEsDvkoN+3k/5R+kWcdrdEes7C5exDKW IXlNuN3IpYb+SN+JittY4vAs9R9Wm88z1S65NQNC4OKthcZMY0EQD7qTM0aROKH/nRaN 4rQw== X-Gm-Message-State: AOAM530BX3YpPvcoPSfm2yHfse1XjMZ7vgO9vpXfhNUszOsJ3q+9Pnr2 iCG+8cxyXEu2FnyHpSDvJyUkqg== X-Google-Smtp-Source: ABdhPJy29foJ9bcVWNWDDSnMOmun1T+EKhKagCWWHZ2uc3dmqwxtcbjTqo+KDuWUfDXITLP/4vQgoQ== X-Received: by 2002:a17:90a:a511:: with SMTP id a17mr5267369pjq.69.1627680406216; Fri, 30 Jul 2021 14:26:46 -0700 (PDT) Received: from tictac2.mtv.corp.google.com ([2620:15c:202:201:3424:e0ac:5a92:d061]) by smtp.gmail.com with ESMTPSA id u21sm3484625pfh.163.2021.07.30.14.26.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jul 2021 14:26:45 -0700 (PDT) From: Douglas Anderson To: Thierry Reding , Rob Herring Cc: Sam Ravnborg , Thomas Zimmermann , Daniel Vetter , dri-devel@lists.freedesktop.org, linux-arm-msm@vger.kernel.org, Maarten Lankhorst , devicetree@vger.kernel.org, David Airlie , Bjorn Andersson , Maxime Ripard , Steev Klimaszewski , Linus W , Douglas Anderson , linux-kernel@vger.kernel.org Subject: [PATCH v2 1/6] dt-bindings: drm/panel-simple: Introduce generic eDP panels Date: Fri, 30 Jul 2021 14:26:20 -0700 Message-Id: <20210730142537.v2.1.I1116e79d34035338a45c1fc7cdd14a097909c8e0@changeid> X-Mailer: git-send-email 2.32.0.554.ge1b32706d8-goog In-Reply-To: <20210730212625.3071831-1-dianders@chromium.org> References: <20210730212625.3071831-1-dianders@chromium.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org eDP panels generally contain almost everything needed to control them in their EDID. This comes from their DP heritage were a computer needs to be able to properly control pretty much any DP display that's plugged into it. The one big issue with eDP panels and the reason that we need a panel driver for them is that the power sequencing can be different per panel. While it is true that eDP panel sequencing can be arbitrarily complex, in practice it turns out that many eDP panels are compatible with just some slightly different delays. See the contents of the bindings file introduced in this patch for some details. The fact that eDP panels are 99% probable and that the power sequencing (especially power up) can be compatible between many panels means that there's a constant desire to plug multiple different panels into the same board. This could be for second sourcing purposes or to support multiple SKUs (maybe a 11" and a 13", for instance). As discussed [1], it should be OK to support this by adding two properties to the device tree to specify the delays needed for powering up the panel the first time. We'll create a new "edp-panel" bindings file and define the two delays that might need to be specified. NOTE: in the vast majority of the cases (HPD is hooked up and isn't glitchy or is debounced) even these delays aren't needed. [1] https://lore.kernel.org/r/CAD=FV=VZYOMPwQZzWdhJGh5cjJWw_EcM-wQVEivZ-bdGXjPrEQ@mail.gmail.com Signed-off-by: Douglas Anderson Reviewed-by: Rob Herring --- Changes in v2: - No longer allow fallback to panel-simple. - Add "-ms" suffix to delays. .../bindings/display/panel/panel-edp.yaml | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/panel-edp.yaml diff --git a/Documentation/devicetree/bindings/display/panel/panel-edp.yaml b/Documentation/devicetree/bindings/display/panel/panel-edp.yaml new file mode 100644 index 000000000000..6a621376ff86 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/panel-edp.yaml @@ -0,0 +1,188 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/panel-edp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Probable (via DP AUX / EDID) eDP Panels with simple poweron sequences + +maintainers: + - Douglas Anderson + +description: | + This binding file can be used to indicate that an eDP panel is connected + to a Embedded DisplayPort AUX bus (see display/dp-aux-bus.yaml) without + actually specifying exactly what panel is connected. This is useful for + the case that more than one different panel could be connected to the + board, either for second-sourcing purposes or to support multiple SKUs + with different LCDs that hook up to a common board. + + As per above, a requirement for using this binding is that the panel is + represented under the DP AUX bus. This means that we can use any + information provided by the DP AUX bus (including the EDID) to identify + the panel. We can use this to identify display size, resolution, and + timings among other things. + + One piece of information about eDP panels that is typically _not_ + provided anywhere on the DP AUX bus is the power sequencing timings. + This is the reason why, historically, we've always had to explicitly + list eDP panels. We solve that here with two tricks. The "worst case" + power on timings for any panels expected to be connected to a board are + specified in these bindings. Once we've powered on, it's expected that + the operating system will lookup the panel in a table (based on EDID + information) to figure out other power sequencing timings. + + eDP panels in general can have somewhat arbitrary power sequencing + requirements. However, even though it's arbitrary in general, the + vast majority of panel datasheets have a power sequence diagram that + looks the exactly the same as every other panel. Each panel datasheet + cares about different timings in this diagram but the fact that the + diagram is so similar means we can come up with a single driver to + handle it. + + These diagrams all look roughly like this, sometimes labeled with + slightly different numbers / lines but all pretty much the same + sequence. This is because much of this diagram comes straight from + the eDP Standard. + + __________________________________________________ + Vdd ___/: :\____ / + _/ : : \_____/ + ::: :<--T10-->::: + : +-----------------------+---------+---------+ + eDP -----------+ Black video | Src vid | Blk vid + + Display : +-----------------------+---------+---------+ + : _______________________:_________:_________: + HPD :| : : | + ___________| : : |_____________ + : : : : + Sink +-----------------------:---------:---------+ + AUX CH -----------+ AUX Ch operational : : +------------- + +-----------------------:---------:---------+ + : : : : + :: :: : : + Src main +------+------+--------------+---------+ + lnk data----------------+LnkTrn| Idle |Valid vid data| Idle/off+------------- + +------+------+--------------+---------+ + : :<-T6->:<-T8->: : + :__:: + LED_EN | | + _____________________________________| |____________________________ + : : + __________:__:_ + PWM | : : | + __________________________| : : |__________________________ + : : : : + _____________:__________:__:_:______ + Bklight ____/: : : : : :\____ + power _______/ :<---T13---->: : : :: \______________ + (Vbl) ::<---------T14--------->: :<-T15->:: + + The above looks fairly complex but, as per above, each panel only cares + about a subset of those timings. + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + const: edp-panel + + hpd-reliable-delay-ms: + description: + A fixed amount of time that must be waited after powering on the + panel's power-supply before the HPD signal is a reliable way to know + when the AUX channel is ready. This is useful for panels that glitch + the HPD at the start of power-on. This value is not needed if HPD is + always reliable for all panels that might be connected. + + hpd-absent-delay-ms: + description: + The panel specifies that HPD will be asserted this many milliseconds + from power on (timing T3 in the diagram above). If we have no way to + measure HPD then a fixed delay of this many milliseconds can be used. + This can also be used as a timeout when waiting for HPD. Does not + include the hpd-reliable-delay, so if hpd-reliable-delay was 80 ms + and hpd-absent-delay was 200 ms then we'd do a fixed 80 ms delay and + then we know HPD would assert in the next 120 ms. This value is not + needed if HPD hooked up, either through a GPIO in the panel node or + hooked up directly to the eDP controller. + + backlight: true + enable-gpios: true + port: true + power-supply: true + no-hpd: true + hpd-gpios: true + +additionalProperties: false + +required: + - compatible + - power-supply + +examples: + - | + #include + #include + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + bridge@2d { + compatible = "ti,sn65dsi86"; + reg = <0x2d>; + + interrupt-parent = <&tlmm>; + interrupts = <10 IRQ_TYPE_LEVEL_HIGH>; + + enable-gpios = <&tlmm 102 GPIO_ACTIVE_HIGH>; + + vpll-supply = <&src_pp1800_s4a>; + vccio-supply = <&src_pp1800_s4a>; + vcca-supply = <&src_pp1200_l2a>; + vcc-supply = <&src_pp1200_l2a>; + + clocks = <&rpmhcc RPMH_LN_BB_CLK2>; + clock-names = "refclk"; + + no-hpd; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + endpoint { + remote-endpoint = <&dsi0_out>; + }; + }; + + port@1 { + reg = <1>; + sn65dsi86_out: endpoint { + remote-endpoint = <&panel_in_edp>; + }; + }; + }; + + aux-bus { + panel { + compatible = "edp-panel"; + power-supply = <&pp3300_dx_edp>; + backlight = <&backlight>; + hpd-gpios = <&sn65dsi86_bridge 2 GPIO_ACTIVE_HIGH>; + hpd-reliable-delay-ms = <15>; + + port { + panel_in_edp: endpoint { + remote-endpoint = <&sn65dsi86_out>; + }; + }; + }; + }; + }; + }; From patchwork Fri Jul 30 21:26:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 489454 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.5 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C6435C4320E for ; Fri, 30 Jul 2021 21:26:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9A30161054 for ; Fri, 30 Jul 2021 21:26:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232346AbhG3V0z (ORCPT ); Fri, 30 Jul 2021 17:26:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35086 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231903AbhG3V0y (ORCPT ); Fri, 30 Jul 2021 17:26:54 -0400 Received: from mail-pj1-x1035.google.com (mail-pj1-x1035.google.com [IPv6:2607:f8b0:4864:20::1035]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4FCCEC061765 for ; Fri, 30 Jul 2021 14:26:48 -0700 (PDT) Received: by mail-pj1-x1035.google.com with SMTP id e2-20020a17090a4a02b029016f3020d867so16244738pjh.3 for ; Fri, 30 Jul 2021 14:26:48 -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=uYCdzD2RDL9hIBzehSSspgpxIEn2gocZn45gaHVVqp8=; b=HS4eIyH1oLZS+CmBFB++Ut4xK71icGOCz5Oa5sQ5WaY4CGiala/9Tm/MpRjaXXwisv f9ZTUC3gkaGxkHICAEhMbGT/3Q+FcqPejwU1ehtRXFUNKcVfIj2Ep7UouTbfpExFny3b udwgzyqsoqPK5YtEtQcAG/H5v6E2hHrCFXBVc= 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=uYCdzD2RDL9hIBzehSSspgpxIEn2gocZn45gaHVVqp8=; b=E8YxdyuDWJtqBnuEgM1zNqOtiBtT+YzFRY1J9jYEfJwujJKF4pujlYdqruF7ZSyoOr szSyCvTcXkwEVjl0Otorc3IzsSKt0zQeeHrT7o0uXAka24Jdsh7i3JtgQZS1o8HX35mj vIK6tf2a1jDe3NYb3Phys4ixNkG9/pTa6bJGAFo6+SqQganm3u9CT9fMvEIaQx7tCh8L /2u/GHz+tetd8FCw6NGyVMloW92NJgaZcZ0s8lJ3UmM/T6NzQxcNuEdPADkl0ig4us5R I8W7YnAFZ3lim4YNa+UvpuuCfb5vrWI7/3oj5C/V9hHlU+lgi/BuUr5OFvCfXJUH3pEn /KTg== X-Gm-Message-State: AOAM5339pFb5ypo6yjtqepF9FRVZHlKzVVtpo/edst8s4o4aSP35zrRU tLoIrbvtCUp9xldDEFG2I4hvtQ== X-Google-Smtp-Source: ABdhPJxecrvjRzXZLeXWPRpkSlm+f0k3Gj52eFV5oTwe28JQaLfLlMEDSJj3cSV4d7vC6DRFaX+GcA== X-Received: by 2002:a17:90a:e7c7:: with SMTP id kb7mr5002308pjb.43.1627680407894; Fri, 30 Jul 2021 14:26:47 -0700 (PDT) Received: from tictac2.mtv.corp.google.com ([2620:15c:202:201:3424:e0ac:5a92:d061]) by smtp.gmail.com with ESMTPSA id u21sm3484625pfh.163.2021.07.30.14.26.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jul 2021 14:26:47 -0700 (PDT) From: Douglas Anderson To: Thierry Reding , Rob Herring Cc: Sam Ravnborg , Thomas Zimmermann , Daniel Vetter , dri-devel@lists.freedesktop.org, linux-arm-msm@vger.kernel.org, Maarten Lankhorst , devicetree@vger.kernel.org, David Airlie , Bjorn Andersson , Maxime Ripard , Steev Klimaszewski , Linus W , Douglas Anderson , linux-kernel@vger.kernel.org Subject: [PATCH v2 2/6] drm/edid: Break out reading block 0 of the EDID Date: Fri, 30 Jul 2021 14:26:21 -0700 Message-Id: <20210730142537.v2.2.I62e76a034ac78c994d40a23cd4ec5aeee56fa77c@changeid> X-Mailer: git-send-email 2.32.0.554.ge1b32706d8-goog In-Reply-To: <20210730212625.3071831-1-dianders@chromium.org> References: <20210730212625.3071831-1-dianders@chromium.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org A future change wants to be able to read just block 0 of the EDID, so break it out of drm_do_get_edid() into a sub-function. This is intended to be a no-op change--just code movement. Signed-off-by: Douglas Anderson --- (no changes since v1) drivers/gpu/drm/drm_edid.c | 62 +++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 81d5f2524246..a623a80f7edb 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1905,6 +1905,43 @@ int drm_add_override_edid_modes(struct drm_connector *connector) } EXPORT_SYMBOL(drm_add_override_edid_modes); +static struct edid *drm_do_get_edid_blk0( + int (*get_edid_block)(void *data, u8 *buf, unsigned int block, + size_t len), + void *data, bool *edid_corrupt, int *null_edid_counter) +{ + int i; + u8 *edid; + + if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) + return NULL; + + /* base block fetch */ + for (i = 0; i < 4; i++) { + if (get_edid_block(data, edid, 0, EDID_LENGTH)) + goto out; + if (drm_edid_block_valid(edid, 0, false, edid_corrupt)) + break; + if (i == 0 && drm_edid_is_zero(edid, EDID_LENGTH)) { + if (null_edid_counter) + (*null_edid_counter)++; + goto carp; + } + } + if (i == 4) + goto carp; + + return (struct edid *)edid; + +carp: + kfree(edid); + return ERR_PTR(-EINVAL); + +out: + kfree(edid); + return NULL; +} + /** * drm_do_get_edid - get EDID data using a custom EDID block read function * @connector: connector we're probing @@ -1938,25 +1975,16 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, if (override) return override; - if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) + edid = (u8 *)drm_do_get_edid_blk0(get_edid_block, data, + &connector->edid_corrupt, + &connector->null_edid_counter); + if (IS_ERR_OR_NULL(edid)) { + if (IS_ERR(edid)) + connector_bad_edid(connector, edid, 1); return NULL; - - /* base block fetch */ - for (i = 0; i < 4; i++) { - if (get_edid_block(data, edid, 0, EDID_LENGTH)) - goto out; - if (drm_edid_block_valid(edid, 0, false, - &connector->edid_corrupt)) - break; - if (i == 0 && drm_edid_is_zero(edid, EDID_LENGTH)) { - connector->null_edid_counter++; - goto carp; - } } - if (i == 4) - goto carp; - /* if there's no extensions, we're done */ + /* if there's no extensions or no connector, we're done */ valid_extensions = edid[0x7e]; if (valid_extensions == 0) return (struct edid *)edid; @@ -2010,8 +2038,6 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, return (struct edid *)edid; -carp: - connector_bad_edid(connector, edid, 1); out: kfree(edid); return NULL; From patchwork Fri Jul 30 21:26:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 489909 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.5 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AC466C4338F for ; Fri, 30 Jul 2021 21:26:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 915F261055 for ; Fri, 30 Jul 2021 21:26:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232441AbhG3V04 (ORCPT ); Fri, 30 Jul 2021 17:26:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35102 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232249AbhG3V04 (ORCPT ); Fri, 30 Jul 2021 17:26:56 -0400 Received: from mail-pj1-x1030.google.com (mail-pj1-x1030.google.com [IPv6:2607:f8b0:4864:20::1030]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0489DC06175F for ; Fri, 30 Jul 2021 14:26:50 -0700 (PDT) Received: by mail-pj1-x1030.google.com with SMTP id l19so17146931pjz.0 for ; Fri, 30 Jul 2021 14:26:50 -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=m7fGDqCOVk/99o7SldtGSKOND5HRxq/duGcx1xikzs4=; b=CITEOH9rWLcR6r4HCqD87CkRbygqLNfMm0gQl/gqd/O/pEz5B1TQtH0gCU+bLeqwwV nk3KydRltFCIAJJSvPKbioUN9fIH03Mj9xyOc7AecylUonU/4mqS9AWZww0mGoVFdicg yxQtiRsUj7pHrvCezePql0kHHC/vV2xQ+mNlw= 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=m7fGDqCOVk/99o7SldtGSKOND5HRxq/duGcx1xikzs4=; b=O5QLh8BOXOVAQi+qqJW/DjVb3JwSXv0+tAPU45Dqp7/hV76VhDo/IczOEmd8OhELPl aSjubAmjT1fXzOcew4mDuwxbtU8B0IZnXYw57d1pZsZgpiLwSr/SvkzuUBoUcO32cba/ GGV6h42/V5GFlIkhUmaypZYBNl3sIoAkexWeI5ICQk6fJz+1+dRrSGAWgVmYy2SJ4u1a m6IKnuQdVgbpLMhBgAL/sXGf5Z/Wa6PWVwWmr/ExNIYZcp7rEYrxQGysrjTkgjCh/dnG d2UuRDxpUnRQ6jVkQRScAvBxvD5KBRQXmrMS4wU8h1osWxL1auziYOAng+X3M6Omy6+g b7KA== X-Gm-Message-State: AOAM533Zs0tRHkYXgYyjp7ckeXvLvCfpPhE22aPl630XAo7A0fcSwiDk rcRMaoC9M5ttG+BWNG9aD4m1dA== X-Google-Smtp-Source: ABdhPJxMcw/Jk9n2pxr/0x29s4VSISye1t5tVGWNpW9qDNcau9N6xmOWq5g0Rm4zK7L6CWjNxIIyZQ== X-Received: by 2002:a17:90b:1981:: with SMTP id mv1mr5204902pjb.227.1627680409577; Fri, 30 Jul 2021 14:26:49 -0700 (PDT) Received: from tictac2.mtv.corp.google.com ([2620:15c:202:201:3424:e0ac:5a92:d061]) by smtp.gmail.com with ESMTPSA id u21sm3484625pfh.163.2021.07.30.14.26.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jul 2021 14:26:49 -0700 (PDT) From: Douglas Anderson To: Thierry Reding , Rob Herring Cc: Sam Ravnborg , Thomas Zimmermann , Daniel Vetter , dri-devel@lists.freedesktop.org, linux-arm-msm@vger.kernel.org, Maarten Lankhorst , devicetree@vger.kernel.org, David Airlie , Bjorn Andersson , Maxime Ripard , Steev Klimaszewski , Linus W , Douglas Anderson , linux-kernel@vger.kernel.org Subject: [PATCH v2 3/6] drm/edid: Allow the querying/working with the panel ID from the EDID Date: Fri, 30 Jul 2021 14:26:22 -0700 Message-Id: <20210730142537.v2.3.I4a672175ba1894294d91d3dbd51da11a8239cf4a@changeid> X-Mailer: git-send-email 2.32.0.554.ge1b32706d8-goog In-Reply-To: <20210730212625.3071831-1-dianders@chromium.org> References: <20210730212625.3071831-1-dianders@chromium.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@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 --- (no changes since v1) drivers/gpu/drm/drm_edid.c | 51 ++++++++++++++++++++++++++++++++++++++ include/drm/drm_edid.h | 47 +++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index a623a80f7edb..43633e083ecd 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2086,6 +2086,57 @@ 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. + */ + val = (u32)edid->mfg_id[0] << 24 | + (u32)edid->mfg_id[1] << 16 | + (u32)edid->prod_code[0] << 8 | + (u32)edid->prod_code[1] << 0; + + 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 759328a5eeb2..75a23caa7709 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); From patchwork Fri Jul 30 21:26:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 489453 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.5 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A51D9C4320A for ; Fri, 30 Jul 2021 21:26:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8DB1560F94 for ; Fri, 30 Jul 2021 21:26:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232572AbhG3V07 (ORCPT ); Fri, 30 Jul 2021 17:26:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35118 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232134AbhG3V04 (ORCPT ); Fri, 30 Jul 2021 17:26:56 -0400 Received: from mail-pj1-x1034.google.com (mail-pj1-x1034.google.com [IPv6:2607:f8b0:4864:20::1034]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9FB9FC06175F for ; Fri, 30 Jul 2021 14:26:51 -0700 (PDT) Received: by mail-pj1-x1034.google.com with SMTP id a4-20020a17090aa504b0290176a0d2b67aso22665534pjq.2 for ; Fri, 30 Jul 2021 14:26:51 -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=37Nacw64+KOiMZmL+vH2rc7D0NFwBJZ1GX41lOzA7sI=; b=k3dRWkT1xUJQUM1V3eFMcOCXVOa7G3HDa077JfJ6+aehexe59cOrNfpB0XemFMroc7 9fP1fXGIEoJ8JUIUXS0nvYt0g7InyqCzjz5uw5aaB6YNXKRPz3KVs6jgRqfLRflWaoNM EtrOjelZ44Et6gdFGNEK/YWJ3uD9WIzm5XkIY= 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=37Nacw64+KOiMZmL+vH2rc7D0NFwBJZ1GX41lOzA7sI=; b=eNhLdwdxKrAttQWOBooj7T2S0IlNKXy5UjeoyOK7K3mT13G3d9L0NIXQyf6MB8BF4u 1EaJ6p2sGCTsFFub/Kxbn1rTZn8vdJ77AadAP6cadjWaAUWF97O11pNEaTYBvtwlzPlt dHQrSxlz9WFaBJsF/Y73ZvelCSKkuWUh7h2HGFdO3WJZmRpWX5PvEEKeo4Mew2T9dF3c 7fZH2CDHTsqB5lL27ExjrVxlSZk9HpoIbylBDAjHWcg8J3JWu+zMoOYaDM16iSztXILE 7VQQy2xM85C0k5KnadKXKL++4F4qxeIjn+wagbQ1Pt2ta/uyXddGyOqOjd+Yxc3AtdaQ a4ng== X-Gm-Message-State: AOAM533gw6T+Thdr+mLcflUWn5kJLwK4xQeb0N+DbfuoMn9AJfyQ70oM Mlx7xEbxwaeV+jA/O19Y+emm+w== X-Google-Smtp-Source: ABdhPJyd5vlwWOM/HeeHAZX/FPiTwLb2eJnUBso0gVxPSxpB1owLbAxI8YeEzKhk0K0yQ86ZtY/f3Q== X-Received: by 2002:a63:2308:: with SMTP id j8mr4059101pgj.166.1627680411233; Fri, 30 Jul 2021 14:26:51 -0700 (PDT) Received: from tictac2.mtv.corp.google.com ([2620:15c:202:201:3424:e0ac:5a92:d061]) by smtp.gmail.com with ESMTPSA id u21sm3484625pfh.163.2021.07.30.14.26.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jul 2021 14:26:50 -0700 (PDT) From: Douglas Anderson To: Thierry Reding , Rob Herring Cc: Sam Ravnborg , Thomas Zimmermann , Daniel Vetter , dri-devel@lists.freedesktop.org, linux-arm-msm@vger.kernel.org, Maarten Lankhorst , devicetree@vger.kernel.org, David Airlie , Bjorn Andersson , Maxime Ripard , Steev Klimaszewski , Linus W , Douglas Anderson , linux-kernel@vger.kernel.org Subject: [PATCH v2 4/6] drm/panel-simple: Don't re-read the EDID every time we power off the panel Date: Fri, 30 Jul 2021 14:26:23 -0700 Message-Id: <20210730142537.v2.4.Ib810fb3bebd0bd6763e4609e1a6764d06064081e@changeid> X-Mailer: git-send-email 2.32.0.554.ge1b32706d8-goog In-Reply-To: <20210730212625.3071831-1-dianders@chromium.org> References: <20210730212625.3071831-1-dianders@chromium.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The simple-panel driver is for panels that are not hot-pluggable at runtime. Let's keep our cached EDID around until driver unload. Signed-off-by: Douglas Anderson --- (no changes since v1) drivers/gpu/drm/panel/panel-simple.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index ff8b59471c71..b06bf30c65d0 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -350,9 +350,6 @@ static int panel_simple_suspend(struct device *dev) regulator_disable(p->supply); p->unprepared_time = ktime_get(); - kfree(p->edid); - p->edid = NULL; - return 0; } @@ -834,6 +831,9 @@ static int panel_simple_remove(struct device *dev) if (panel->ddc && (!panel->aux || panel->ddc != &panel->aux->ddc)) put_device(&panel->ddc->dev); + kfree(panel->edid); + panel->edid = NULL; + return 0; } From patchwork Fri Jul 30 21:26:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 489908 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.5 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 13163C4320A for ; Fri, 30 Jul 2021 21:27:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0148D60F46 for ; Fri, 30 Jul 2021 21:26:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232786AbhG3V1D (ORCPT ); Fri, 30 Jul 2021 17:27:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35132 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232134AbhG3V1A (ORCPT ); Fri, 30 Jul 2021 17:27:00 -0400 Received: from mail-pl1-x62c.google.com (mail-pl1-x62c.google.com [IPv6:2607:f8b0:4864:20::62c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AF5FDC0613C1 for ; Fri, 30 Jul 2021 14:26:53 -0700 (PDT) Received: by mail-pl1-x62c.google.com with SMTP id z3so11294709plg.8 for ; Fri, 30 Jul 2021 14:26:53 -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=/9pe0vp/2S/yyqFRQwYtuI91YF1fj5/j9qd/6MVyxqs=; b=BHXVq1MELYCtBV1DweXqBcVD2kudADL1JM8qpK0g3TeRhog1FtBWSIOx+tkx0O2qeR f0uNhIkDdWYsdXndWcG4IeUH9hqRqUc84qcym81SiRG6Sm3AS1vYv15zDyEN4rp3RLcI 4qNTMUpBQgkmsR043IFfKWNnWLfZnFcZHfa5I= 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=/9pe0vp/2S/yyqFRQwYtuI91YF1fj5/j9qd/6MVyxqs=; b=F9shWAFM8Vc73v+ayCjEX0LIkYDHtTksCH227N2df3lcvB8zNIrszGks4b35s+icIF yfLQm8ZG+g4ej+wtqTNWAohpjfWMzWWH8FPxQn4zU9N9YRfhMzRQjLnNE9aiFg0M0AGN d2sWIH2uxEGFwJq8agV/m/PMYosGAE58ZDV+jeY1fM/rFOkqBjDBX8z6GyktpK20p8es 4n/n7CyKEOe6dwXYVafOj++p8mUTJqHOOiXxBxtD87JsxKtwp43FoF03k4LhR2RCOced obqwHmYkS2Jsb4Fs9DB/s52q/nLMHQgFZMt88Mw9NEzfaK4IMC2ypdkWs1EfLsBMBdH6 UyNw== X-Gm-Message-State: AOAM530VJQeAqgfxm/Bo2uR7Td+5QyJuuRB7D0cfBnjx3uXKJA5Fen3L 5nGD5IznJ18s5rwX6SX0gLwJNQ== X-Google-Smtp-Source: ABdhPJxBN3lxm1xi3KDrnnKCQfeCE7CY6sVtsiHHzl5j9dYSm4NyqWLxct5ErQnSu186qB/gdEC1Pg== X-Received: by 2002:a62:7c4d:0:b029:3b0:b284:fd9c with SMTP id x74-20020a627c4d0000b02903b0b284fd9cmr2739725pfc.11.1627680413218; Fri, 30 Jul 2021 14:26:53 -0700 (PDT) Received: from tictac2.mtv.corp.google.com ([2620:15c:202:201:3424:e0ac:5a92:d061]) by smtp.gmail.com with ESMTPSA id u21sm3484625pfh.163.2021.07.30.14.26.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jul 2021 14:26:52 -0700 (PDT) From: Douglas Anderson To: Thierry Reding , Rob Herring Cc: Sam Ravnborg , Thomas Zimmermann , Daniel Vetter , dri-devel@lists.freedesktop.org, linux-arm-msm@vger.kernel.org, Maarten Lankhorst , devicetree@vger.kernel.org, David Airlie , Bjorn Andersson , Maxime Ripard , Steev Klimaszewski , Linus W , Douglas Anderson , linux-kernel@vger.kernel.org Subject: [PATCH v2 5/6] drm/panel-simple: Split the delay structure out of the panel description Date: Fri, 30 Jul 2021 14:26:24 -0700 Message-Id: <20210730142537.v2.5.I11c226341f8e86d376a53d5ec11cb82f6fd2c38c@changeid> X-Mailer: git-send-email 2.32.0.554.ge1b32706d8-goog In-Reply-To: <20210730212625.3071831-1-dianders@chromium.org> References: <20210730212625.3071831-1-dianders@chromium.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org In the case where we can read an EDID for a panel the only part of the panel description that can't be found directly from the EDID is the description of the delays. Let's break the delay structure out so that we can specify just the delays for panels that are detected by EDID. This is simple code motion. No functional change is intended. Signed-off-by: Douglas Anderson --- Changes in v2: - Rebased atop revert of delays between GPIO & regulator drivers/gpu/drm/panel/panel-simple.c | 159 ++++++++++++++------------- 1 file changed, 82 insertions(+), 77 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index b06bf30c65d0..7d80bb20e6e0 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -41,6 +41,87 @@ #include #include +/** + * struct panel_delay - Describes delays for a simple panel. + */ +struct panel_delay { + /** + * @prepare: Time for the panel to become ready. + * + * The time (in milliseconds) that it takes for the panel to + * become ready and start receiving video data + */ + unsigned int prepare; + + /** + * @hpd_absent_delay: Time to wait if HPD isn't hooked up. + * + * Add this to the prepare delay if we know Hot Plug Detect + * isn't used. + */ + unsigned int hpd_absent_delay; + + /** + * @prepare_to_enable: Time between prepare and enable. + * + * The minimum time, in milliseconds, that needs to have passed + * between when prepare finished and enable may begin. If at + * enable time less time has passed since prepare finished, + * the driver waits for the remaining time. + * + * If a fixed enable delay is also specified, we'll start + * counting before delaying for the fixed delay. + * + * If a fixed prepare delay is also specified, we won't start + * counting until after the fixed delay. We can't overlap this + * fixed delay with the min time because the fixed delay + * doesn't happen at the end of the function if a HPD GPIO was + * specified. + * + * In other words: + * prepare() + * ... + * // do fixed prepare delay + * // wait for HPD GPIO if applicable + * // start counting for prepare_to_enable + * + * enable() + * // do fixed enable delay + * // enforce prepare_to_enable min time + */ + unsigned int prepare_to_enable; + + /** + * @enable: Time for the panel to display a valid frame. + * + * The time (in milliseconds) that it takes for the panel to + * display the first valid frame after starting to receive + * video data. + */ + unsigned int enable; + + /** + * @disable: Time for the panel to turn the display off. + * + * The time (in milliseconds) that it takes for the panel to + * turn the display off (no content is visible). + */ + unsigned int disable; + + /** + * @unprepare: Time to power down completely. + * + * The time (in milliseconds) that it takes for the panel + * to power itself down completely. + * + * This time is used to prevent a future "prepare" from + * starting until at least this many milliseconds has passed. + * If at prepare time less time has passed since unprepare + * finished, the driver waits for the remaining time. + */ + unsigned int unprepare; +}; + /** * struct panel_desc - Describes a simple panel. */ @@ -85,83 +166,7 @@ struct panel_desc { } size; /** @delay: Structure containing various delay values for this panel. */ - struct { - /** - * @delay.prepare: Time for the panel to become ready. - * - * The time (in milliseconds) that it takes for the panel to - * become ready and start receiving video data - */ - unsigned int prepare; - - /** - * @delay.hpd_absent_delay: Time to wait if HPD isn't hooked up. - * - * Add this to the prepare delay if we know Hot Plug Detect - * isn't used. - */ - unsigned int hpd_absent_delay; - - /** - * @delay.prepare_to_enable: Time between prepare and enable. - * - * The minimum time, in milliseconds, that needs to have passed - * between when prepare finished and enable may begin. If at - * enable time less time has passed since prepare finished, - * the driver waits for the remaining time. - * - * If a fixed enable delay is also specified, we'll start - * counting before delaying for the fixed delay. - * - * If a fixed prepare delay is also specified, we won't start - * counting until after the fixed delay. We can't overlap this - * fixed delay with the min time because the fixed delay - * doesn't happen at the end of the function if a HPD GPIO was - * specified. - * - * In other words: - * prepare() - * ... - * // do fixed prepare delay - * // wait for HPD GPIO if applicable - * // start counting for prepare_to_enable - * - * enable() - * // do fixed enable delay - * // enforce prepare_to_enable min time - */ - unsigned int prepare_to_enable; - - /** - * @delay.enable: Time for the panel to display a valid frame. - * - * The time (in milliseconds) that it takes for the panel to - * display the first valid frame after starting to receive - * video data. - */ - unsigned int enable; - - /** - * @delay.disable: Time for the panel to turn the display off. - * - * The time (in milliseconds) that it takes for the panel to - * turn the display off (no content is visible). - */ - unsigned int disable; - - /** - * @delay.unprepare: Time to power down completely. - * - * The time (in milliseconds) that it takes for the panel - * to power itself down completely. - * - * This time is used to prevent a future "prepare" from - * starting until at least this many milliseconds has passed. - * If at prepare time less time has passed since unprepare - * finished, the driver waits for the remaining time. - */ - unsigned int unprepare; - } delay; + struct panel_delay delay; /** @bus_format: See MEDIA_BUS_FMT_... defines. */ u32 bus_format; From patchwork Fri Jul 30 21:26:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 489452 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.5 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 16420C4320E for ; Fri, 30 Jul 2021 21:27:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F1E2960F46 for ; Fri, 30 Jul 2021 21:27:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232466AbhG3V1E (ORCPT ); Fri, 30 Jul 2021 17:27:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35142 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232589AbhG3V1B (ORCPT ); Fri, 30 Jul 2021 17:27:01 -0400 Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 704A3C0613D3 for ; Fri, 30 Jul 2021 14:26:55 -0700 (PDT) Received: by mail-pj1-x102d.google.com with SMTP id o44-20020a17090a0a2fb0290176ca3e5a2fso16248349pjo.1 for ; Fri, 30 Jul 2021 14:26:55 -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=40YzoOKug0ixPZC7Um9F1pMdUxsZSDrw3C3GC0yN/wo=; b=b3U+OIE36tvfWGdz32hS2b3udSR9smFz5iYrAiqc8Yl5qEcIT1Y5Ji9OACPB77frhm u0yd25/GEOX4ESrp4SdRfoPtC9W3Dgd201sdyauMot6NGE3YhsrxCiPrVV6/1qqk1t5o oh1N7YTggnrWziK3/vhZ6YgwoJ20bLMG/Dc1w= 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=40YzoOKug0ixPZC7Um9F1pMdUxsZSDrw3C3GC0yN/wo=; b=WAKayjnq+bw/N1obGp7LuolPs30nNDO5ua2YrmRG03S7+jAQc81SOw8HacjEgTmePW bmsl2KVm5L52q8Id8TnafaJ/RgrLPBRSGeidsQf77E9+xzoAI8bINpjsig+caRrwySg1 rt8sW+6Zs0LHFQyTAZDKL0ODlhzr5e/LWoZ+mToBDEMqdiZ0jmOQnWuiFxAcIJpTvXB8 gXvfHrwFZBBBbtO6AOKPFRddpBg470kItYeTBZKxgSJ9SXBcI1kdJGMepY9jIAASROE6 32v1UI14/jUP/WZNZnprVLS0IVUZzYGUJATVt81TA729LvoCevQAModZ6S4HvKFfEgGM UZ9A== X-Gm-Message-State: AOAM531RnhMONW92Wy+eka6sHZPNVHqCYpSga7Z1fK3gFsQQl2vf1Unq CxCvh4hWqX3+k7vAjqIHK2yMng== X-Google-Smtp-Source: ABdhPJzLSbhRO7dIdUOC8tS755XOPwEQeylZ8cDdmIiDi+ZWJbdJVbcNu2MD3JVk7FUVO/F2HH9Gpw== X-Received: by 2002:a17:90b:4c12:: with SMTP id na18mr5073398pjb.157.1627680414976; Fri, 30 Jul 2021 14:26:54 -0700 (PDT) Received: from tictac2.mtv.corp.google.com ([2620:15c:202:201:3424:e0ac:5a92:d061]) by smtp.gmail.com with ESMTPSA id u21sm3484625pfh.163.2021.07.30.14.26.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Jul 2021 14:26:54 -0700 (PDT) From: Douglas Anderson To: Thierry Reding , Rob Herring Cc: Sam Ravnborg , Thomas Zimmermann , Daniel Vetter , dri-devel@lists.freedesktop.org, linux-arm-msm@vger.kernel.org, Maarten Lankhorst , devicetree@vger.kernel.org, David Airlie , Bjorn Andersson , Maxime Ripard , Steev Klimaszewski , Linus W , Douglas Anderson , linux-kernel@vger.kernel.org Subject: [PATCH v2 6/6] drm/panel-simple: Implement generic "edp-panel"s probed by EDID Date: Fri, 30 Jul 2021 14:26:25 -0700 Message-Id: <20210730142537.v2.6.Id9c96cba4eba3e5ee519bfb09cd64b39f2490293@changeid> X-Mailer: git-send-email 2.32.0.554.ge1b32706d8-goog In-Reply-To: <20210730212625.3071831-1-dianders@chromium.org> References: <20210730212625.3071831-1-dianders@chromium.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org As discussed in the patch ("dt-bindings: drm/panel-simple: Introduce generic eDP panels") we can actually support probing eDP panels at runtime instead of hardcoding what panel is connected. Add support to the panel-simple driver for this. We'll implement a solution like this: * We'll read in two delays from the device tree that are used for powering up the panel the initial time (to read the EDID). * In the EDID we can find a 32-bit ID that identifies what panel we've found. From this ID we can look up the full set of delays. After this change we'll still need to add per-panel delays into the panel-simple driver but we will no longer need to specify exactly which panel is connected to which board in the device tree. Nicely, any panels that are only supported this way also don't need to hardcode mode data since it's guaranteed that we can get that through the EDID. This patch will seed the ID-to-delay table with a few panels that I have access to, many of which are on sc7180-trogdor devices. Signed-off-by: Douglas Anderson --- Changes in v2: - Don't support a "fallback" panel. Probed panels must be probed. - Not based on patch to copy "desc"--just allocate for probed panels. - Add "-ms" suffix to delays. drivers/gpu/drm/panel/panel-simple.c | 187 ++++++++++++++++++++++++--- 1 file changed, 171 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 7d80bb20e6e0..c2a2168f9a13 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -178,6 +178,20 @@ struct panel_desc { int connector_type; }; +/** + * struct edp_panel_entry - Maps panel ID to delay / panel name. + */ +struct edp_panel_entry { + /** @panel_id: 32-bit ID for panel, encoded with encode_edid_id(). */ + u32 panel_id; + + /* @delay: The power sequencing delays needed for this panel. */ + const struct panel_delay *delay; + + /* @name: Name of this panel (for printing to logs). */ + const char *name; +}; + struct panel_simple { struct drm_panel base; bool enabled; @@ -532,8 +546,15 @@ static int panel_simple_get_modes(struct drm_panel *panel, pm_runtime_put_autosuspend(panel->dev); } - /* add hard-coded panel modes */ - num += panel_simple_get_non_edid_modes(p, connector); + /* + * Add hard-coded panel modes. Don't call this if there are no timings + * and no modes (the generic edp-panel case) because it will clobber + * the display_info that was already set by drm_add_edid_modes(). + */ + if (p->desc->num_timings || p->desc->num_modes) + num += panel_simple_get_non_edid_modes(p, connector); + else if (!num) + dev_warn(p->base.dev, "No display modes\n"); /* set up connector's "panel orientation" property */ drm_connector_set_panel_orientation(connector, p->orientation); @@ -662,9 +683,79 @@ static void panel_simple_parse_panel_timing_node(struct device *dev, dev_err(dev, "Reject override mode: No display_timing found\n"); } +static const struct edp_panel_entry *find_edp_panel(u32 panel_id); + +static int generic_edp_panel_probe(struct device *dev, struct panel_simple *panel) +{ + const struct edp_panel_entry *edp_panel; + struct panel_desc *desc; + u32 panel_id; + char vend[4]; + u16 product_id; + u32 prepare_ms = 0; + u32 absent_ms = 0; + int ret; + + desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + desc->connector_type = DRM_MODE_CONNECTOR_eDP; + panel->desc = desc; + + /* + * Read the dts properties for the initial probe. These are used by + * the runtime resume code which will get called by the + * pm_runtime_get_sync() call below. + */ + of_property_read_u32(dev->of_node, "hpd-reliable-delay-ms", &prepare_ms); + desc->delay.prepare = prepare_ms; + of_property_read_u32(dev->of_node, "hpd-absent-delay-ms", &absent_ms); + if (absent_ms && absent_ms <= prepare_ms) + dev_warn(dev, + "Ignoring hpd-absent-delay-ms <= hpd-reliable-delay-ms\n"); + else if (absent_ms) + /* + * hpd_absent_delay is added to prepare delay in prepare, + * so subtract since dts bindings are specified slightly + * that they overlap. + */ + desc->delay.hpd_absent_delay = absent_ms - prepare_ms; + + /* Power the panel on so we can read the EDID */ + pm_runtime_get_sync(dev); + + panel_id = drm_get_panel_id(panel->ddc); + if (!panel_id) { + dev_err(dev, "Couldn't identify panel via EDID\n"); + ret = -EIO; + goto exit; + } + decode_edid_id(panel_id, vend, &product_id); + + edp_panel = find_edp_panel(panel_id); + if (!edp_panel) { + dev_err(dev, "Unrecognized panel %s %#06x\n", vend, product_id); + ret = -EINVAL; + goto exit; + } + + dev_info(dev, "Detected %s %s (%#06x)\n", vend, edp_panel->name, product_id); + + /* Update the delay; everything else comes from EDID */ + desc->delay = *edp_panel->delay; + + ret = 0; +exit: + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + static int panel_simple_probe(struct device *dev, const struct panel_desc *desc, struct drm_dp_aux *aux) { + bool is_generic_edp_panel = false; struct panel_simple *panel; struct display_timing dt; struct device_node *ddc; @@ -728,6 +819,29 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc, panel_simple_parse_panel_timing_node(dev, panel, &dt); } + dev_set_drvdata(dev, panel); + + /* + * We use runtime PM for prepare / unprepare since those power the panel + * on and off and those can be very slow operations. This is important + * to optimize powering the panel on briefly to read the EDID before + * fully enabling the panel. + */ + pm_runtime_enable(dev); + pm_runtime_set_autosuspend_delay(dev, 1000); + pm_runtime_use_autosuspend(dev); + + if (of_device_is_compatible(dev->of_node, "edp-panel")) { + is_generic_edp_panel = true; + + err = generic_edp_panel_probe(dev, panel); + if (err) + return dev_err_probe(dev, err, + "Couldn't detect panel nor find a fallback\n"); + /* generic_edp_panel_probe() replaces desc in the panel */ + desc = panel->desc; + } + connector_type = desc->connector_type; /* Catch common mistakes for panels. */ switch (connector_type) { @@ -751,7 +865,7 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc, desc->bpc != 8); break; case DRM_MODE_CONNECTOR_eDP: - if (desc->bpc != 6 && desc->bpc != 8 && desc->bpc != 10) + if (!is_generic_edp_panel && desc->bpc != 6 && desc->bpc != 8 && desc->bpc != 10) dev_warn(dev, "Expected bpc in {6,8,10} but got: %u\n", desc->bpc); break; case DRM_MODE_CONNECTOR_DSI: @@ -782,18 +896,6 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc, break; } - dev_set_drvdata(dev, panel); - - /* - * We use runtime PM for prepare / unprepare since those power the panel - * on and off and those can be very slow operations. This is important - * to optimize powering the panel on briefly to read the EDID before - * fully enabling the panel. - */ - pm_runtime_enable(dev); - pm_runtime_set_autosuspend_delay(dev, 1000); - pm_runtime_use_autosuspend(dev); - drm_panel_init(&panel->base, dev, &panel_simple_funcs, connector_type); err = drm_panel_of_backlight(&panel->base); @@ -4281,6 +4383,9 @@ static const struct panel_desc arm_rtsm = { static const struct of_device_id platform_of_match[] = { { + /* Must be first */ + .compatible = "edp-panel", + }, { .compatible = "ampire,am-1280800n3tzqw-t00h", .data = &ire_am_1280800n3tzqw_t00h, }, { @@ -4707,11 +4812,61 @@ static const struct of_device_id platform_of_match[] = { }; MODULE_DEVICE_TABLE(of, platform_of_match); +static const struct panel_delay boe_nv116whm_t01_delay = { + .hpd_absent_delay = 200, + .prepare_to_enable = 80, + .unprepare = 500, +}; + +#define EDP_PANEL_ENTRY(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name) \ +{ \ + .name = _name, \ + .panel_id = encode_edid_id(vend_chr_0, vend_chr_1, vend_chr_2, product_id), \ + .delay = _delay \ +} + +/* + * This table is used to figure out power sequencing delays for panels that + * are detected by EDID. Entries here may point to entries in the + * platform_of_match table (if a panel is listed in both places). + * + * Sort first by vendor, then by product ID. + */ +static const struct edp_panel_entry edp_panels[] = { + EDP_PANEL_ENTRY('A', 'U', 'O', 0x5c40, &auo_b116xak01.delay, "B116XAK01"), + + EDP_PANEL_ENTRY('B', 'O', 'E', 0x2d08, &boe_nv133fhm_n61.delay, "NV133FHM-N62"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x8607, &boe_nv116whm_t01_delay, "NV116WHM-T01"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x8d09, &boe_nv110wtm_n61.delay, "NV110WTM-N61"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0xd107, &boe_nv133fhm_n61.delay, "NV133FHM-N61"), + + EDP_PANEL_ENTRY('C', 'M', 'N', 0x4c11, &innolux_n116bca_ea1.delay, "N116BCA-EA1"), + + EDP_PANEL_ENTRY('K', 'D', 'B', 0x2406, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"), + + { /* sentinal */ } +}; + +static const struct edp_panel_entry *find_edp_panel(u32 panel_id) +{ + const struct edp_panel_entry *panel; + + if (!panel_id) + return NULL; + + for (panel = edp_panels; panel->panel_id; panel++) + if (panel->panel_id == panel_id) + return panel; + + return NULL; +} + static int panel_simple_platform_probe(struct platform_device *pdev) { const struct of_device_id *id; - id = of_match_node(platform_of_match, pdev->dev.of_node); + /* Skip one since "edp-panel" is only supported on DP AUX bus */ + id = of_match_node(platform_of_match + 1, pdev->dev.of_node); if (!id) return -ENODEV;