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: 12411951 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 395B2C4338F 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 2232060F46 for ; Fri, 30 Jul 2021 21:26:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231939AbhG3V0y (ORCPT ); Fri, 30 Jul 2021 17:26:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35068 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231903AbhG3V0w (ORCPT ); Fri, 30 Jul 2021 17:26:52 -0400 Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A9B92C0613C1 for ; Fri, 30 Jul 2021 14:26:46 -0700 (PDT) Received: by mail-pl1-x635.google.com with SMTP id e5so12605719pld.6 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=dR9/VMDDhE6FFZq+wtT6QKWeCjs9OPojV+8esgIleM7GX+Jnyt/8kNHjQekWXZcRof 6cDrTjWU+dQhnuUXhHq4yX3O7YM65+iyhE6Ugr80ClpgCgS3Q7hx51LGlsBz9V3kIgTu fRtVjCc2kXQV+d1k+JT/rLtgrXkhvwAxCQ54JKbWrYu4wfpKEOwAhZtQ0nscdD7SKl48 t3XN2nv2zmsg0tn0nB4l3G6ADX54hF+1BFQIdOg7vEmHAMXR80zFjMSgeRmbno5lDmtH 9ILZGg5rOm/Ka0bqjV+AXO7HcMONjgn5u5zWSG7ArZg4rsU41DdfEgpBy6W2qESZuDLn I8lA== X-Gm-Message-State: AOAM530f/BjmOqbGmsCDpO/KzaySLJNiLncYM2e/KItwiOSDaIJxdkJD RBQhILObUj0NTjAL04n6iKJlXg== 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: linux-arm-msm@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: 12411953 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 6FE4EC43214 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 5FAB761076 for ; Fri, 30 Jul 2021 21:26:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232284AbhG3V0z (ORCPT ); Fri, 30 Jul 2021 17:26:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35084 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232249AbhG3V0y (ORCPT ); Fri, 30 Jul 2021 17:26:54 -0400 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4F285C06175F for ; Fri, 30 Jul 2021 14:26:48 -0700 (PDT) Received: by mail-pj1-x102c.google.com with SMTP id pj14-20020a17090b4f4eb029017786cf98f9so5606708pjb.2 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=S7FLIGoAnicpVbZ5zCq3RE+j/UrRz6Di1dEYn0q6yvoTO535nfRJN/KO+JYzzRUWEQ Y7PSkh9zfvcuM85DAcZubxxbET1fuL7Tee4wC2GVR4LKQnjBlwT6MAnyqTwd7Bh33Ulb ntaH1ZHa6hbG+ZgdjeV/L9h4utXfzfjuYSOPIZUlrpiGDay6tXpxao4z137iYUTLrmYr xGAuf4L1cwKefp8uSoY2/ORXBdyQTizimYcO9mlbZs9eGl7W8OLrqY+1Of/ArrniALSv y2SIwTkB6EgV+rDDX1XCbVcnNtFx+6ggoC7ISqWHHPaTmLKYwpbUAfziEGQ3NWPhqFiM sXRw== X-Gm-Message-State: AOAM531stc1T/tJhfvXShSt8o4m8BI2wzswkLt/VqH7vtGqwWtNOC8wZ Kqt1r287H/KBTHJihF7JTSzo6bhtjjH9EIH7 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: linux-arm-msm@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: 12411957 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 28E54C4338F for ; Fri, 30 Jul 2021 21:26:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1254960F3A for ; Fri, 30 Jul 2021 21:26:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232743AbhG3V1C (ORCPT ); Fri, 30 Jul 2021 17:27:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35106 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232533AbhG3V06 (ORCPT ); Fri, 30 Jul 2021 17:26:58 -0400 Received: from mail-pj1-x102e.google.com (mail-pj1-x102e.google.com [IPv6:2607:f8b0:4864:20::102e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0D56AC0613CF for ; Fri, 30 Jul 2021 14:26:50 -0700 (PDT) Received: by mail-pj1-x102e.google.com with SMTP id pj14-20020a17090b4f4eb029017786cf98f9so5606823pjb.2 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=m7caA9JfRF8epVlR62T7jzE3ZucyEM4LkBEWeeydg8qUINd36Z/Cgv0pMS80t0PRaF 6PIHnER9wGr+SZTXp8No8SKGpjTtz1adYfrARA1i/E0HoEGGaez2o0DpyKbDMTIb08Bv sP2pUqEAKxw+guldALeip7S9PkR7ga9R/obEsYKNfQFgKDgK/LAZeiJ1KsWmHqGZAIAB AkaM8OIl8AaOw9JgKBYwuJZC5xmJwrgDLNn358RcpYxxSW20AuJVfQm+WHUu385TlOvV tmYwEKllfSTpZEgadlNCdh/oadwXX1c+LcexHs+2zneCa/G8G5EJ0XShtXZYF5N0Pykb 9wtQ== X-Gm-Message-State: AOAM532k4WDU1af1KlT21yQyb/9oD/i7i1YcttnNmR0f2RY3syjU4vBO d9MrJSZ8X+iKT1D2xzLZlWyfWg== 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: linux-arm-msm@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: 12411955 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 AE133C43214 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 9A7DD60F46 for ; Fri, 30 Jul 2021 21:26:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231903AbhG3V07 (ORCPT ); Fri, 30 Jul 2021 17:26:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35122 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232460AbhG3V04 (ORCPT ); Fri, 30 Jul 2021 17:26:56 -0400 Received: from mail-pj1-x102e.google.com (mail-pj1-x102e.google.com [IPv6:2607:f8b0:4864:20::102e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A18BAC0613C1 for ; Fri, 30 Jul 2021 14:26:51 -0700 (PDT) Received: by mail-pj1-x102e.google.com with SMTP id m10-20020a17090a34cab0290176b52c60ddso16194799pjf.4 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=mEZ/IQHRBk9RgWw4QIHImoWsTLUZk3LxVHBOI3EuJYmaJS5yrrvmzPYwOLN1UzzlPT /bVNEGvL/Gqwy4OkM5FEecuaqNplb3UDz0sDFltRLLBmrxXxxAJPAfOauan8Rkasall6 H23MLNVAiIevE4ow9POppVXxktVlMVkKQ1MR1MzjWcBEurBQqQlerE5utAUGIvIVNcUE MD+KyNOrL3IYvjrG69XQCD0hXY2M1r90NyyShmKKu+pOTIpMXXawFCNeXWueL1wcedYj 0f0SQZvksRYpbzWNnAqwbZ7QKLLgJvEYn8hfNXfeiskAw/kpNE75qzCJgPI6Yh3BBXsw 4s3Q== X-Gm-Message-State: AOAM5302R6VTiXlNd+EpdyuuIS0XhDsIaqLDijdfr5fhNeSNxHp1aCy7 92yAORMSB/5rCHqtx1K2D970cw== 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: linux-arm-msm@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: 12411959 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 5F136C43214 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 48A7560F3A for ; Fri, 30 Jul 2021 21:27:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232774AbhG3V1D (ORCPT ); Fri, 30 Jul 2021 17:27:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35122 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230004AbhG3V07 (ORCPT ); Fri, 30 Jul 2021 17:26:59 -0400 Received: from mail-pj1-x102a.google.com (mail-pj1-x102a.google.com [IPv6:2607:f8b0:4864:20::102a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A19E5C06175F for ; Fri, 30 Jul 2021 14:26:53 -0700 (PDT) Received: by mail-pj1-x102a.google.com with SMTP id o44-20020a17090a0a2fb0290176ca3e5a2fso16248275pjo.1 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=snfzWBh3ziRIGeg77dBMDu/T/jOnzoKnwxV+UIuMHMSxYcJMg4VmXOlbnDdva0OItz 5E8qt1Cc4aQhpMwrKCDFHgY+jLIGvrfOZsn8LjdKswvOll/WBoptmqOf9hPZu5FosOCn k92SEevE03omjfRLwnH2yFZLCbzfmrtoqBeO6JyXzon+SUN7jf8iwH1LeVqPpfIijCv5 Xmeczj4HaPwxioBzg+Hao97hkb2Jvw/NWD9Z8CTx8aPZT0JGzyQmdVyaEA2NRYe0Nny/ K27JkEj7R9Ir4oSjBd4X+oytmlRRrqCo7CfxM43nZbLOvU9ETYorVgOeoj1cmwIewqjp Tl4w== X-Gm-Message-State: AOAM5321AsyNLnt8UzzaRFhdpAR0FBbYZfEvtaP7SFQFKD+XRqWwf0qz tZ3l3aXJYPBtW80nCyld6N/6eg== 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: linux-arm-msm@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: 12411961 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 935BBC4338F for ; Fri, 30 Jul 2021 21:27:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7C41560F3A for ; Fri, 30 Jul 2021 21:27:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232817AbhG3V1J (ORCPT ); Fri, 30 Jul 2021 17:27:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35144 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232663AbhG3V1B (ORCPT ); Fri, 30 Jul 2021 17:27:01 -0400 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 718CFC0613D5 for ; Fri, 30 Jul 2021 14:26:55 -0700 (PDT) Received: by mail-pj1-x102c.google.com with SMTP id q17-20020a17090a2e11b02901757deaf2c8so16407326pjd.0 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=Ld/ylrjFczU8aencCSxNPRa7f4PxR+xtpvojb1sftIeMNR1JkrHau0UenBd0jRjzUs tfeyO2RaPjBw5uLaYW8eM25H9UQ+JA5EjmH73HnDIwWF6sioJOdx+gXX5rAtgFXEJ1dl AZXA85p9PlxxIZFitwhLzQ+RQCArZg7n15XdDejets/gpMbXvsC+WTLh3zCutX6rRNAn NhM8DCgNaYjkqI0gso5LQaZGd93GzcCq/X3vQ9nplSKpMPbos6mdh7aNjayfKdm38cmv 5MHLjwLDf0oBvboMnT8lnvfHCxpqNNVeBWLAQMymZGO3yn5FZt/DNTDAtgJ7C4WD4YR5 RaTg== X-Gm-Message-State: AOAM533OHnF+b0zp6iUb+m6lCN3kd20jQMaSuPAW9CGYiP5QlE1/6qTY 1CcGXwib/MlFkbQhbqd4eaH4bQ== 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: linux-arm-msm@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;