Message ID | 20230425034010.3789376-6-quic_bjorande@quicinc.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp3151653vqo; Mon, 24 Apr 2023 20:42:20 -0700 (PDT) X-Google-Smtp-Source: AKy350Zx+zCLt5NNy/Z/nUlpPKBBgUsYkeYtNvd+BAOfl0hwE1jMk7lJgtHw/yFAsamudgsj4dIQ X-Received: by 2002:a05:6a20:8683:b0:ef:e017:c60f with SMTP id k3-20020a056a20868300b000efe017c60fmr15830478pze.51.1682394139756; Mon, 24 Apr 2023 20:42:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1682394139; cv=none; d=google.com; s=arc-20160816; b=aLeV2aWvKO1NYHL8o1hA/Ns9x7Koc5dKA9PbPNpFg/y6HxyYpmRfeaEiOL0HJRNEiG 5iHmkhqiha81aA4S6jIr1JH+5NAqHFP4KPYfbbRqd2nk51MtDRQfg8ARK7al/UBNUX75 kbeeCLNjTU93NcsArSbN4PQUdJwceUjmSK5k77SYZ9cBxdKuU1hRz8oiu9zOFIfzT2Ce vIyu41yUkkCt7y2z19yXzSTyYtrbr9ds/0ujHh2qgfVRp9mOLDcll2BCSIg7q8uXQx4U MdzPXX4QjqnTE4jHtw4Aqc5kIyL4/upf0Hpj6NdAs0TqCkkGj9icT743PScp3X65/z3l evnw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=bvX2vYXIK5cZmgjxE+3RHUQVscZvlNVm5kEYWLq3lP8=; b=veRkLyk5Y52VULtqWyBw75GghPFttvKpY3ZDDiOefaDu/CapmQFo7XfLBnqQBPnwRR +gHYJMzUsanirvijUyDcV5zSHPVbm/yw5WV2DmHbGsSK5kqpScbXqNAjqgMCDA5OGHYV 6BwkBehe7FJE4ZH8HnIpQf3lsPKmQwUfZm11uvOFlsfdXEdkitIIK0SAMhiI/HF+4HuJ YZ/kxGj1fYqdNIqvu0g6dcGwTgNsITUCUpJJOVjffvuqRa+vAQoK6xzEx35+kAwE28tI b4WjhGoauN/5rOS5KSgTTbdnF9F9OQALeuts0J8JygseSR5ltV4ABTuwj/c1Lj/zYg38 PrwQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=E+BqtKuk; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id k28-20020aa7973c000000b0063d37ae9543si12890191pfg.28.2023.04.24.20.42.05; Mon, 24 Apr 2023 20:42:19 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=E+BqtKuk; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233193AbjDYDkt (ORCPT <rfc822;fengqi706@gmail.com> + 99 others); Mon, 24 Apr 2023 23:40:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53318 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233263AbjDYDk0 (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Mon, 24 Apr 2023 23:40:26 -0400 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6F7E049E5; Mon, 24 Apr 2023 20:40:25 -0700 (PDT) Received: from pps.filterd (m0279868.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 33P0xmG8004207; Tue, 25 Apr 2023 03:40:18 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=qcppdkim1; bh=bvX2vYXIK5cZmgjxE+3RHUQVscZvlNVm5kEYWLq3lP8=; b=E+BqtKuklLqmus8vMW0PGYL0wl2YP9MawXUrY5fuJzmUtuauWfhDgfsmLB19LEoi1VHQ 1L0cF+kGekxJLnx15+u8HjmrnN8R6p0ZhNRVt0WmeyOTrjfEfWNXg4vm77KGrKNw2auz ZgN4OFX+feNIamCSz1nm3QhmPn6/Obm7vQEjmogL5ZDclgN9Kg5jBK7O+DqbRiY7pexc 2xyymTDa//S9cwNl/U4fvBMfnNTk4DYEWvDgcZfxmAGyEsiKXfLPYQVc3BxSFQGFKkE+ rffEBWjGn2+Vrkp0FoHLpdLXXB/OnOmc4lWu8j2ibvk92YfrYdu60S8/+sjEp+FESACO Lg== Received: from nalasppmta01.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3q5tk4hjg6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 25 Apr 2023 03:40:18 +0000 Received: from nalasex01c.na.qualcomm.com (nalasex01c.na.qualcomm.com [10.47.97.35]) by NALASPPMTA01.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 33P3eHOY024339 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 25 Apr 2023 03:40:17 GMT Received: from hu-bjorande-lv.qualcomm.com (10.49.16.6) by nalasex01c.na.qualcomm.com (10.47.97.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.42; Mon, 24 Apr 2023 20:40:17 -0700 From: Bjorn Andersson <quic_bjorande@quicinc.com> To: Vinod Koul <vkoul@kernel.org>, Kishon Vijay Abraham I <kishon@kernel.org>, Johan Hovold <johan@kernel.org> CC: Bjorn Andersson <andersson@kernel.org>, Konrad Dybcio <konrad.dybcio@linaro.org>, Rob Herring <robh+dt@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, <linux-arm-msm@vger.kernel.org>, <linux-phy@lists.infradead.org>, <devicetree@vger.kernel.org>, <linux-kernel@vger.kernel.org> Subject: [PATCH 5/7] phy: qcom-qmp-combo: Introduce drm_bridge Date: Mon, 24 Apr 2023 20:40:08 -0700 Message-ID: <20230425034010.3789376-6-quic_bjorande@quicinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230425034010.3789376-1-quic_bjorande@quicinc.com> References: <20230425034010.3789376-1-quic_bjorande@quicinc.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01b.na.qualcomm.com (10.47.209.197) To nalasex01c.na.qualcomm.com (10.47.97.35) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: LvqiY1XxRLtCB4JwAZpiN4ZmGT6nrRFF X-Proofpoint-GUID: LvqiY1XxRLtCB4JwAZpiN4ZmGT6nrRFF X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.942,Hydra:6.0.573,FMLib:17.11.170.22 definitions=2023-04-25_03,2023-04-21_01,2023-02-09_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 adultscore=0 mlxlogscore=999 suspectscore=0 clxscore=1015 malwarescore=0 impostorscore=0 bulkscore=0 lowpriorityscore=0 phishscore=0 priorityscore=1501 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2303200000 definitions=main-2304250031 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1764118117852268515?= X-GMAIL-MSGID: =?utf-8?q?1764118117852268515?= |
Series |
phy: qcom-qmp-combo: Support orientation switching
|
|
Commit Message
Bjorn Andersson
April 25, 2023, 3:40 a.m. UTC
The QMP combo PHY sits in an of_graph connected between the DisplayPort
controller and a USB Type-C connector (or possibly a redriver).
The TCPM needs to be able to convey the HPD signal to the DisplayPort
controller, but no directly link is provided by DeviceTree so the signal
needs to "pass through" the QMP combo phy.
Handle this by introducing a drm_bridge which upon initialization finds
the next bridge (i.e. the usb-c-connector) and chain this together. This
way HPD changes in the connector will propagate to the DisplayPort
driver.
The connector bridge is resolved lazily, as the TCPM is expected to be
able to resolve the typec mux and switch at probe time, so the QMP combo
phy will probe before the TCPM.
Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
---
drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 36 +++++++++++++++++++++++
1 file changed, 36 insertions(+)
Comments
On Tue, Apr 25, 2023 at 4:40 AM Bjorn Andersson <quic_bjorande@quicinc.com> wrote: > > The QMP combo PHY sits in an of_graph connected between the DisplayPort > controller and a USB Type-C connector (or possibly a redriver). > > The TCPM needs to be able to convey the HPD signal to the DisplayPort > controller, but no directly link is provided by DeviceTree so the signal > needs to "pass through" the QMP combo phy. > > Handle this by introducing a drm_bridge which upon initialization finds > the next bridge (i.e. the usb-c-connector) and chain this together. This > way HPD changes in the connector will propagate to the DisplayPort > driver. > > The connector bridge is resolved lazily, as the TCPM is expected to be > able to resolve the typec mux and switch at probe time, so the QMP combo > phy will probe before the TCPM. > > Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com> > --- > drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 36 +++++++++++++++++++++++ > 1 file changed, 36 insertions(+) > > diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > index 5d6d6ef3944b..84bc08002537 100644 > --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > @@ -22,6 +22,8 @@ > #include <linux/usb/typec.h> > #include <linux/usb/typec_mux.h> > > +#include <drm/drm_bridge.h> > + > #include <dt-bindings/phy/phy-qcom-qmp.h> > > #include "phy-qcom-qmp.h" > @@ -1332,6 +1334,8 @@ struct qmp_combo { > struct clk_hw dp_link_hw; > struct clk_hw dp_pixel_hw; > > + struct drm_bridge bridge; > + > struct typec_switch_dev *sw; > enum typec_orientation orientation; > }; > @@ -3196,6 +3200,34 @@ static int qmp_combo_register_clocks(struct qmp_combo *qmp, struct device_node * > return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, dp_np); > } > > +static int qmp_combo_bridge_attach(struct drm_bridge *bridge, > + enum drm_bridge_attach_flags flags) > +{ > + struct qmp_combo *qmp = container_of(bridge, struct qmp_combo, bridge); > + struct drm_bridge *next_bridge; > + > + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) > + return -EINVAL; > + > + next_bridge = devm_drm_of_get_bridge(qmp->dev, qmp->dev->of_node, 0, 0); > + if (IS_ERR(next_bridge)) > + return dev_err_probe(qmp->dev, PTR_ERR(next_bridge), "failed to acquire drm_bridge\n"); > + > + return drm_bridge_attach(bridge->encoder, next_bridge, bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR); > +} > + > +static const struct drm_bridge_funcs qmp_combo_bridge_funcs = { > + .attach = qmp_combo_bridge_attach, > +}; > + > +static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) > +{ > + qmp->bridge.funcs = &qmp_combo_bridge_funcs; > + qmp->bridge.of_node = qmp->dev->of_node; > + > + return devm_drm_bridge_add(qmp->dev, &qmp->bridge); > +} > + > static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_node *np) > { > struct device *dev = qmp->dev; > @@ -3459,6 +3491,10 @@ static int qmp_combo_probe(struct platform_device *pdev) > if (ret) > return ret; > > + ret = qmp_combo_dp_register_bridge(qmp); > + if (ret) > + return ret; > + > /* Check for legacy binding with child nodes. */ > usb_np = of_get_child_by_name(dev->of_node, "usb3-phy"); > if (usb_np) { > -- > 2.39.2 > You need to add some or all of these select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_HELPER select DRM_DP_AUX_BUS select DRM_KMS_HELPER select DRM_MIPI_DSI select DRM_PANEL /opt/linaro/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ld: Unexpected GOT/PLT entries detected! /opt/linaro/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ld: Unexpected run-time procedure linkages detected! drivers/phy/qualcomm/phy-qcom-qmp-combo.o: In function `qmp_combo_bridge_attach': phy-qcom-qmp-combo.c:(.text+0xb50): undefined reference to `devm_drm_of_get_bridge' phy-qcom-qmp-combo.c:(.text+0xb6c): undefined reference to `drm_bridge_attach' drivers/phy/qualcomm/phy-qcom-qmp-combo.o: In function `qmp_combo_probe': phy-qcom-qmp-combo.c:(.text+0x13fc): undefined reference to `devm_drm_bridge_add' --- bod
On 26/04/2023 12:33, Bryan O'Donoghue wrote: > On Tue, Apr 25, 2023 at 4:40 AM Bjorn Andersson > <quic_bjorande@quicinc.com> wrote: >> >> The QMP combo PHY sits in an of_graph connected between the DisplayPort >> controller and a USB Type-C connector (or possibly a redriver). >> >> The TCPM needs to be able to convey the HPD signal to the DisplayPort >> controller, but no directly link is provided by DeviceTree so the signal >> needs to "pass through" the QMP combo phy. >> >> Handle this by introducing a drm_bridge which upon initialization finds >> the next bridge (i.e. the usb-c-connector) and chain this together. This >> way HPD changes in the connector will propagate to the DisplayPort >> driver. >> >> The connector bridge is resolved lazily, as the TCPM is expected to be >> able to resolve the typec mux and switch at probe time, so the QMP combo >> phy will probe before the TCPM. >> >> Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com> >> --- >> drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 36 +++++++++++++++++++++++ >> 1 file changed, 36 insertions(+) >> >> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c >> index 5d6d6ef3944b..84bc08002537 100644 >> --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c >> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c >> @@ -22,6 +22,8 @@ >> #include <linux/usb/typec.h> >> #include <linux/usb/typec_mux.h> >> >> +#include <drm/drm_bridge.h> >> + >> #include <dt-bindings/phy/phy-qcom-qmp.h> >> >> #include "phy-qcom-qmp.h" >> @@ -1332,6 +1334,8 @@ struct qmp_combo { >> struct clk_hw dp_link_hw; >> struct clk_hw dp_pixel_hw; >> >> + struct drm_bridge bridge; >> + >> struct typec_switch_dev *sw; >> enum typec_orientation orientation; >> }; >> @@ -3196,6 +3200,34 @@ static int qmp_combo_register_clocks(struct qmp_combo *qmp, struct device_node * >> return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, dp_np); >> } >> >> +static int qmp_combo_bridge_attach(struct drm_bridge *bridge, >> + enum drm_bridge_attach_flags flags) >> +{ >> + struct qmp_combo *qmp = container_of(bridge, struct qmp_combo, bridge); >> + struct drm_bridge *next_bridge; >> + >> + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) >> + return -EINVAL; >> + >> + next_bridge = devm_drm_of_get_bridge(qmp->dev, qmp->dev->of_node, 0, 0); >> + if (IS_ERR(next_bridge)) >> + return dev_err_probe(qmp->dev, PTR_ERR(next_bridge), "failed to acquire drm_bridge\n"); >> + >> + return drm_bridge_attach(bridge->encoder, next_bridge, bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR); >> +} >> + >> +static const struct drm_bridge_funcs qmp_combo_bridge_funcs = { >> + .attach = qmp_combo_bridge_attach, >> +}; >> + >> +static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) >> +{ >> + qmp->bridge.funcs = &qmp_combo_bridge_funcs; >> + qmp->bridge.of_node = qmp->dev->of_node; >> + >> + return devm_drm_bridge_add(qmp->dev, &qmp->bridge); >> +} >> + >> static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_node *np) >> { >> struct device *dev = qmp->dev; >> @@ -3459,6 +3491,10 @@ static int qmp_combo_probe(struct platform_device *pdev) >> if (ret) >> return ret; >> >> + ret = qmp_combo_dp_register_bridge(qmp); >> + if (ret) >> + return ret; I think the DRM part should be only built if CONFIG_DRM is enabled, I don't have a strong opinion on this, I think Vinod could help here. >> + >> /* Check for legacy binding with child nodes. */ >> usb_np = of_get_child_by_name(dev->of_node, "usb3-phy"); >> if (usb_np) { >> -- >> 2.39.2 >> > > You need to add some or all of these > select DRM_DISPLAY_DP_HELPER > select DRM_DISPLAY_HELPER > select DRM_DP_AUX_BUS > select DRM_KMS_HELPER > select DRM_MIPI_DSI > select DRM_PANEL > > > /opt/linaro/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ld: > Unexpected GOT/PLT entries detected! > /opt/linaro/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ld: > Unexpected run-time procedure linkages detected! > drivers/phy/qualcomm/phy-qcom-qmp-combo.o: In function > `qmp_combo_bridge_attach': > phy-qcom-qmp-combo.c:(.text+0xb50): undefined reference to > `devm_drm_of_get_bridge' > phy-qcom-qmp-combo.c:(.text+0xb6c): undefined reference to `drm_bridge_attach' > drivers/phy/qualcomm/phy-qcom-qmp-combo.o: In function `qmp_combo_probe': > phy-qcom-qmp-combo.c:(.text+0x13fc): undefined reference to > `devm_drm_bridge_add' I think CONFIG_DRM_PANEL_BRIDGE in addition to CONFIG_DRM. should be enough. With this config added and my drm-bridge hat: Acked-by: Neil Armstrong <neil.armstrong@linaro.org> Neil > > --- > bod
On 27/04/2023 16:11, Neil Armstrong wrote: > On 26/04/2023 12:33, Bryan O'Donoghue wrote: >> On Tue, Apr 25, 2023 at 4:40 AM Bjorn Andersson >> <quic_bjorande@quicinc.com> wrote: >>> >>> The QMP combo PHY sits in an of_graph connected between the DisplayPort >>> controller and a USB Type-C connector (or possibly a redriver). >>> >>> The TCPM needs to be able to convey the HPD signal to the DisplayPort >>> controller, but no directly link is provided by DeviceTree so the signal >>> needs to "pass through" the QMP combo phy. >>> >>> Handle this by introducing a drm_bridge which upon initialization finds >>> the next bridge (i.e. the usb-c-connector) and chain this together. This >>> way HPD changes in the connector will propagate to the DisplayPort >>> driver. >>> >>> The connector bridge is resolved lazily, as the TCPM is expected to be >>> able to resolve the typec mux and switch at probe time, so the QMP combo >>> phy will probe before the TCPM. >>> >>> Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com> >>> --- >>> drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 36 +++++++++++++++++++++++ >>> 1 file changed, 36 insertions(+) >>> >>> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c >>> b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c >>> index 5d6d6ef3944b..84bc08002537 100644 >>> --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c >>> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c >>> @@ -22,6 +22,8 @@ >>> #include <linux/usb/typec.h> >>> #include <linux/usb/typec_mux.h> >>> >>> +#include <drm/drm_bridge.h> >>> + >>> #include <dt-bindings/phy/phy-qcom-qmp.h> >>> >>> #include "phy-qcom-qmp.h" >>> @@ -1332,6 +1334,8 @@ struct qmp_combo { >>> struct clk_hw dp_link_hw; >>> struct clk_hw dp_pixel_hw; >>> >>> + struct drm_bridge bridge; >>> + >>> struct typec_switch_dev *sw; >>> enum typec_orientation orientation; >>> }; >>> @@ -3196,6 +3200,34 @@ static int qmp_combo_register_clocks(struct >>> qmp_combo *qmp, struct device_node * >>> return devm_add_action_or_reset(qmp->dev, >>> phy_clk_release_provider, dp_np); >>> } >>> >>> +static int qmp_combo_bridge_attach(struct drm_bridge *bridge, >>> + enum drm_bridge_attach_flags flags) >>> +{ >>> + struct qmp_combo *qmp = container_of(bridge, struct >>> qmp_combo, bridge); >>> + struct drm_bridge *next_bridge; >>> + >>> + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) >>> + return -EINVAL; >>> + >>> + next_bridge = devm_drm_of_get_bridge(qmp->dev, >>> qmp->dev->of_node, 0, 0); >>> + if (IS_ERR(next_bridge)) >>> + return dev_err_probe(qmp->dev, PTR_ERR(next_bridge), >>> "failed to acquire drm_bridge\n"); >>> + >>> + return drm_bridge_attach(bridge->encoder, next_bridge, >>> bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR); >>> +} >>> + >>> +static const struct drm_bridge_funcs qmp_combo_bridge_funcs = { >>> + .attach = qmp_combo_bridge_attach, >>> +}; >>> + >>> +static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) >>> +{ >>> + qmp->bridge.funcs = &qmp_combo_bridge_funcs; >>> + qmp->bridge.of_node = qmp->dev->of_node; >>> + >>> + return devm_drm_bridge_add(qmp->dev, &qmp->bridge); >>> +} >>> + >>> static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, >>> struct device_node *np) >>> { >>> struct device *dev = qmp->dev; >>> @@ -3459,6 +3491,10 @@ static int qmp_combo_probe(struct >>> platform_device *pdev) >>> if (ret) >>> return ret; >>> >>> + ret = qmp_combo_dp_register_bridge(qmp); >>> + if (ret) >>> + return ret; > > I think the DRM part should be only built if CONFIG_DRM is enabled, I don't > have a strong opinion on this, I think Vinod could help here. > >>> + >>> /* Check for legacy binding with child nodes. */ >>> usb_np = of_get_child_by_name(dev->of_node, "usb3-phy"); >>> if (usb_np) { >>> -- >>> 2.39.2 >>> >> >> You need to add some or all of these >> select DRM_DISPLAY_DP_HELPER >> select DRM_DISPLAY_HELPER >> select DRM_DP_AUX_BUS >> select DRM_KMS_HELPER >> select DRM_MIPI_DSI >> select DRM_PANEL >> >> >> /opt/linaro/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ld: >> Unexpected GOT/PLT entries detected! >> /opt/linaro/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ld: >> Unexpected run-time procedure linkages detected! >> drivers/phy/qualcomm/phy-qcom-qmp-combo.o: In function >> `qmp_combo_bridge_attach': >> phy-qcom-qmp-combo.c:(.text+0xb50): undefined reference to >> `devm_drm_of_get_bridge' >> phy-qcom-qmp-combo.c:(.text+0xb6c): undefined reference to >> `drm_bridge_attach' >> drivers/phy/qualcomm/phy-qcom-qmp-combo.o: In function `qmp_combo_probe': >> phy-qcom-qmp-combo.c:(.text+0x13fc): undefined reference to >> `devm_drm_bridge_add' > > I think CONFIG_DRM_PANEL_BRIDGE in addition to CONFIG_DRM. should be > enough. > I'd say DRM_PANEL_BRIDGE || !DRM_PANEL_BRIDGE in addition to DRM. And we probably should fix the devm_drm_of_get_bridge() stub to use drm_of_find_panel_or_bridge() with panel = NULL. > With this config added and my drm-bridge hat: > > Acked-by: Neil Armstrong <neil.armstrong@linaro.org> > > Neil > > >> >> --- >> bod >
On Wed, Apr 26, 2023 at 11:33:40AM +0100, Bryan O'Donoghue wrote: > On Tue, Apr 25, 2023 at 4:40 AM Bjorn Andersson > <quic_bjorande@quicinc.com> wrote: > > [..] > You need to add some or all of these > select DRM_DISPLAY_DP_HELPER > select DRM_DISPLAY_HELPER > select DRM_DP_AUX_BUS > select DRM_KMS_HELPER > select DRM_MIPI_DSI > select DRM_PANEL > > > /opt/linaro/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ld: > Unexpected GOT/PLT entries detected! > /opt/linaro/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ld: > Unexpected run-time procedure linkages detected! > drivers/phy/qualcomm/phy-qcom-qmp-combo.o: In function > `qmp_combo_bridge_attach': > phy-qcom-qmp-combo.c:(.text+0xb50): undefined reference to > `devm_drm_of_get_bridge' > phy-qcom-qmp-combo.c:(.text+0xb6c): undefined reference to `drm_bridge_attach' > drivers/phy/qualcomm/phy-qcom-qmp-combo.o: In function `qmp_combo_probe': > phy-qcom-qmp-combo.c:(.text+0x13fc): undefined reference to > `devm_drm_bridge_add' > You're correct, and TYPEC. Realized that I forgot these once I had posted the patches. Will figure out the actual set for v2. Thanks, Bjorn
On Thu, Apr 27, 2023 at 8:56 PM Bjorn Andersson <quic_bjorande@quicinc.com> wrote: > > On Wed, Apr 26, 2023 at 11:33:40AM +0100, Bryan O'Donoghue wrote: > > On Tue, Apr 25, 2023 at 4:40 AM Bjorn Andersson > > <quic_bjorande@quicinc.com> wrote: > > > > [..] > > You need to add some or all of these > > select DRM_DISPLAY_DP_HELPER > > select DRM_DISPLAY_HELPER > > select DRM_DP_AUX_BUS > > select DRM_KMS_HELPER > > select DRM_MIPI_DSI > > select DRM_PANEL > > > > > > /opt/linaro/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ld: > > Unexpected GOT/PLT entries detected! > > /opt/linaro/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ld: > > Unexpected run-time procedure linkages detected! > > drivers/phy/qualcomm/phy-qcom-qmp-combo.o: In function > > `qmp_combo_bridge_attach': > > phy-qcom-qmp-combo.c:(.text+0xb50): undefined reference to > > `devm_drm_of_get_bridge' > > phy-qcom-qmp-combo.c:(.text+0xb6c): undefined reference to `drm_bridge_attach' > > drivers/phy/qualcomm/phy-qcom-qmp-combo.o: In function `qmp_combo_probe': > > phy-qcom-qmp-combo.c:(.text+0x13fc): undefined reference to > > `devm_drm_bridge_add' > > > > You're correct, and TYPEC. Realized that I forgot these once I had > posted the patches. Will figure out the actual set for v2. > > Thanks, > Bjorn So I added CONFIG_DRM to Kconfig for the combo phy and then replaced the old patch we had with your series. Works for me with my TCPM set with zero changes - aside from slotting the old PHY patch with your expanded series on SM8250 Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> https://git.codelinaro.org/bryan.odonoghue/kernel/-/tree/linux-next-23-04-28-pm8150b-tcpm-qcom-wrapper-typec-mux-bjorn
On Mon, Apr 24, 2023 at 08:40:08PM -0700, Bjorn Andersson wrote: > The QMP combo PHY sits in an of_graph connected between the DisplayPort > controller and a USB Type-C connector (or possibly a redriver). > > The TCPM needs to be able to convey the HPD signal to the DisplayPort > controller, but no directly link is provided by DeviceTree so the signal > needs to "pass through" the QMP combo phy. > > Handle this by introducing a drm_bridge which upon initialization finds > the next bridge (i.e. the usb-c-connector) and chain this together. This > way HPD changes in the connector will propagate to the DisplayPort > driver. > > The connector bridge is resolved lazily, as the TCPM is expected to be > able to resolve the typec mux and switch at probe time, so the QMP combo > phy will probe before the TCPM. > > Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com> > --- > drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 36 +++++++++++++++++++++++ > 1 file changed, 36 insertions(+) > > diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > index 5d6d6ef3944b..84bc08002537 100644 > --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > @@ -22,6 +22,8 @@ > #include <linux/usb/typec.h> > #include <linux/usb/typec_mux.h> > > +#include <drm/drm_bridge.h> > + > #include <dt-bindings/phy/phy-qcom-qmp.h> > > #include "phy-qcom-qmp.h" > @@ -1332,6 +1334,8 @@ struct qmp_combo { > struct clk_hw dp_link_hw; > struct clk_hw dp_pixel_hw; > > + struct drm_bridge bridge; > + > struct typec_switch_dev *sw; > enum typec_orientation orientation; > }; > @@ -3196,6 +3200,34 @@ static int qmp_combo_register_clocks(struct qmp_combo *qmp, struct device_node * > return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, dp_np); > } > > +static int qmp_combo_bridge_attach(struct drm_bridge *bridge, > + enum drm_bridge_attach_flags flags) > +{ > + struct qmp_combo *qmp = container_of(bridge, struct qmp_combo, bridge); > + struct drm_bridge *next_bridge; > + > + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) > + return -EINVAL; > + > + next_bridge = devm_drm_of_get_bridge(qmp->dev, qmp->dev->of_node, 0, 0); > + if (IS_ERR(next_bridge)) > + return dev_err_probe(qmp->dev, PTR_ERR(next_bridge), "failed to acquire drm_bridge\n"); Using dev_err_probe() in an attach callback looks wrong as these functions should not be returning -EPROBE_DEFER (and this is not a probe function). > + > + return drm_bridge_attach(bridge->encoder, next_bridge, bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR); This line is over 100 chars, but there should be no reason not to break it before 80 here. > +} > + > +static const struct drm_bridge_funcs qmp_combo_bridge_funcs = { > + .attach = qmp_combo_bridge_attach, > +}; > + > +static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) > +{ > + qmp->bridge.funcs = &qmp_combo_bridge_funcs; > + qmp->bridge.of_node = qmp->dev->of_node; > + > + return devm_drm_bridge_add(qmp->dev, &qmp->bridge); > +} Guess you need a dummy function also for qmp_combo_dp_register_bridge() in case of !CONFIG_DRM. > + > static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_node *np) > { > struct device *dev = qmp->dev; > @@ -3459,6 +3491,10 @@ static int qmp_combo_probe(struct platform_device *pdev) > if (ret) > return ret; > > + ret = qmp_combo_dp_register_bridge(qmp); > + if (ret) > + return ret; > + > /* Check for legacy binding with child nodes. */ > usb_np = of_get_child_by_name(dev->of_node, "usb3-phy"); > if (usb_np) { Johan
On Tue, May 02, 2023 at 02:05:53PM +0200, Johan Hovold wrote: > On Mon, Apr 24, 2023 at 08:40:08PM -0700, Bjorn Andersson wrote: > > The QMP combo PHY sits in an of_graph connected between the DisplayPort > > controller and a USB Type-C connector (or possibly a redriver). > > > > The TCPM needs to be able to convey the HPD signal to the DisplayPort > > controller, but no directly link is provided by DeviceTree so the signal > > needs to "pass through" the QMP combo phy. > > > > Handle this by introducing a drm_bridge which upon initialization finds > > the next bridge (i.e. the usb-c-connector) and chain this together. This > > way HPD changes in the connector will propagate to the DisplayPort > > driver. > > > > The connector bridge is resolved lazily, as the TCPM is expected to be > > able to resolve the typec mux and switch at probe time, so the QMP combo > > phy will probe before the TCPM. > > > > Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com> > > --- > > drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 36 +++++++++++++++++++++++ > > 1 file changed, 36 insertions(+) > > > > diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > > index 5d6d6ef3944b..84bc08002537 100644 > > --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > > +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > > @@ -22,6 +22,8 @@ > > #include <linux/usb/typec.h> > > #include <linux/usb/typec_mux.h> > > > > +#include <drm/drm_bridge.h> > > + > > #include <dt-bindings/phy/phy-qcom-qmp.h> > > > > #include "phy-qcom-qmp.h" > > @@ -1332,6 +1334,8 @@ struct qmp_combo { > > struct clk_hw dp_link_hw; > > struct clk_hw dp_pixel_hw; > > > > + struct drm_bridge bridge; > > + > > struct typec_switch_dev *sw; > > enum typec_orientation orientation; > > }; > > @@ -3196,6 +3200,34 @@ static int qmp_combo_register_clocks(struct qmp_combo *qmp, struct device_node * > > return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, dp_np); > > } > > > > +static int qmp_combo_bridge_attach(struct drm_bridge *bridge, > > + enum drm_bridge_attach_flags flags) > > +{ > > + struct qmp_combo *qmp = container_of(bridge, struct qmp_combo, bridge); > > + struct drm_bridge *next_bridge; > > + > > + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) > > + return -EINVAL; > > + > > + next_bridge = devm_drm_of_get_bridge(qmp->dev, qmp->dev->of_node, 0, 0); > > + if (IS_ERR(next_bridge)) > > + return dev_err_probe(qmp->dev, PTR_ERR(next_bridge), "failed to acquire drm_bridge\n"); > > Using dev_err_probe() in an attach callback looks wrong as these > functions should not be returning -EPROBE_DEFER (and this is not a probe > function). > The problem is that this might return EPROBE_DEFER, and at least today propagates out to returning EPROBE_DEFER from our DP controller's bind(). This is not optimal, but unfortunately we have a two way dependency across the of_graph, so we need to make one of the sides lazy... > > + > > + return drm_bridge_attach(bridge->encoder, next_bridge, bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR); > > This line is over 100 chars, but there should be no reason not to break > it before 80 here. > > > +} > > + > > +static const struct drm_bridge_funcs qmp_combo_bridge_funcs = { > > + .attach = qmp_combo_bridge_attach, > > +}; > > + > > +static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) > > +{ > > + qmp->bridge.funcs = &qmp_combo_bridge_funcs; > > + qmp->bridge.of_node = qmp->dev->of_node; > > + > > + return devm_drm_bridge_add(qmp->dev, &qmp->bridge); > > +} > > Guess you need a dummy function also for qmp_combo_dp_register_bridge() > in case of !CONFIG_DRM. > Right, missed that dependency. Will wrap this and provide a dummy. Thanks, Bjorn > > + > > static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_node *np) > > { > > struct device *dev = qmp->dev; > > @@ -3459,6 +3491,10 @@ static int qmp_combo_probe(struct platform_device *pdev) > > if (ret) > > return ret; > > > > + ret = qmp_combo_dp_register_bridge(qmp); > > + if (ret) > > + return ret; > > + > > /* Check for legacy binding with child nodes. */ > > usb_np = of_get_child_by_name(dev->of_node, "usb3-phy"); > > if (usb_np) { > > Johan
On Wed, May 03, 2023 at 08:13:54PM -0700, Bjorn Andersson wrote: > On Tue, May 02, 2023 at 02:05:53PM +0200, Johan Hovold wrote: > > On Mon, Apr 24, 2023 at 08:40:08PM -0700, Bjorn Andersson wrote: > > > The QMP combo PHY sits in an of_graph connected between the DisplayPort > > > controller and a USB Type-C connector (or possibly a redriver). > > > > > > The TCPM needs to be able to convey the HPD signal to the DisplayPort > > > controller, but no directly link is provided by DeviceTree so the signal > > > needs to "pass through" the QMP combo phy. > > > > > > Handle this by introducing a drm_bridge which upon initialization finds > > > the next bridge (i.e. the usb-c-connector) and chain this together. This > > > way HPD changes in the connector will propagate to the DisplayPort > > > driver. > > > > > > The connector bridge is resolved lazily, as the TCPM is expected to be > > > able to resolve the typec mux and switch at probe time, so the QMP combo > > > phy will probe before the TCPM. > > > > > > Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com> > > > --- > > > drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 36 +++++++++++++++++++++++ > > > 1 file changed, 36 insertions(+) > > > > > > diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > > > index 5d6d6ef3944b..84bc08002537 100644 > > > --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > > > +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > > > @@ -3196,6 +3200,34 @@ static int qmp_combo_register_clocks(struct qmp_combo *qmp, struct device_node * > > > return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, dp_np); > > > } > > > > > > +static int qmp_combo_bridge_attach(struct drm_bridge *bridge, > > > + enum drm_bridge_attach_flags flags) > > > +{ > > > + struct qmp_combo *qmp = container_of(bridge, struct qmp_combo, bridge); > > > + struct drm_bridge *next_bridge; > > > + > > > + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) > > > + return -EINVAL; > > > + > > > + next_bridge = devm_drm_of_get_bridge(qmp->dev, qmp->dev->of_node, 0, 0); > > > + if (IS_ERR(next_bridge)) > > > + return dev_err_probe(qmp->dev, PTR_ERR(next_bridge), "failed to acquire drm_bridge\n"); > > > > Using dev_err_probe() in an attach callback looks wrong as these > > functions should not be returning -EPROBE_DEFER (and this is not a probe > > function). > > The problem is that this might return EPROBE_DEFER, and at least today > propagates out to returning EPROBE_DEFER from our DP controller's > bind(). Due to the known issue with the MSM driver panel lookup, or due to some more fundamental problem with the stack? At least in the former case, I don't think we should hide the fact that we have an unresolved issue with the MSM driver this way even if it means printing an extra error message until it has been resolved (cf. the panel lookup errors that we've intentionally kept in place). > This is not optimal, but unfortunately we have a two way dependency > across the of_graph, so we need to make one of the sides lazy... But this comments seems to suggest this is a bigger issue than the panel lookup. Could you describe the issue in some more detail (e.g. when would you see -EPROBE_DEFER here)? Johan
On Thu, 4 May 2023 at 11:38, Johan Hovold <johan@kernel.org> wrote: > > On Wed, May 03, 2023 at 08:13:54PM -0700, Bjorn Andersson wrote: > > On Tue, May 02, 2023 at 02:05:53PM +0200, Johan Hovold wrote: > > > On Mon, Apr 24, 2023 at 08:40:08PM -0700, Bjorn Andersson wrote: > > > > The QMP combo PHY sits in an of_graph connected between the DisplayPort > > > > controller and a USB Type-C connector (or possibly a redriver). > > > > > > > > The TCPM needs to be able to convey the HPD signal to the DisplayPort > > > > controller, but no directly link is provided by DeviceTree so the signal > > > > needs to "pass through" the QMP combo phy. > > > > > > > > Handle this by introducing a drm_bridge which upon initialization finds > > > > the next bridge (i.e. the usb-c-connector) and chain this together. This > > > > way HPD changes in the connector will propagate to the DisplayPort > > > > driver. > > > > > > > > The connector bridge is resolved lazily, as the TCPM is expected to be > > > > able to resolve the typec mux and switch at probe time, so the QMP combo > > > > phy will probe before the TCPM. > > > > > > > > Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com> > > > > --- > > > > drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 36 +++++++++++++++++++++++ > > > > 1 file changed, 36 insertions(+) > > > > > > > > diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > > > > index 5d6d6ef3944b..84bc08002537 100644 > > > > --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > > > > +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > > > > > @@ -3196,6 +3200,34 @@ static int qmp_combo_register_clocks(struct qmp_combo *qmp, struct device_node * > > > > return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, dp_np); > > > > } > > > > > > > > +static int qmp_combo_bridge_attach(struct drm_bridge *bridge, > > > > + enum drm_bridge_attach_flags flags) > > > > +{ > > > > + struct qmp_combo *qmp = container_of(bridge, struct qmp_combo, bridge); > > > > + struct drm_bridge *next_bridge; > > > > + > > > > + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) > > > > + return -EINVAL; > > > > + > > > > + next_bridge = devm_drm_of_get_bridge(qmp->dev, qmp->dev->of_node, 0, 0); > > > > + if (IS_ERR(next_bridge)) > > > > + return dev_err_probe(qmp->dev, PTR_ERR(next_bridge), "failed to acquire drm_bridge\n"); > > > > > > Using dev_err_probe() in an attach callback looks wrong as these > > > functions should not be returning -EPROBE_DEFER (and this is not a probe > > > function). > > > > The problem is that this might return EPROBE_DEFER, and at least today > > propagates out to returning EPROBE_DEFER from our DP controller's > > bind(). > > Due to the known issue with the MSM driver panel lookup, or due to some > more fundamental problem with the stack? Ideally MSM DP driver should call component_add() only when the next bridge is available. This is how we handle it for the DSI case. However I'm yet to see the changes to dp_display_probe() which make actual use of the done_probing callback. And even that will only fix the eDP case. For the normal DP case we have no way of being properly notified when the next bridge becomes available. So the driver will try to drm_bridge_attach() from the component's bind() callback and return an error if the chain is not (yet) fully available. > > At least in the former case, I don't think we should hide the fact that > we have an unresolved issue with the MSM driver this way even if it > means printing an extra error message until it has been resolved (cf. > the panel lookup errors that we've intentionally kept in place). > > > This is not optimal, but unfortunately we have a two way dependency > > across the of_graph, so we need to make one of the sides lazy... > > But this comments seems to suggest this is a bigger issue than the panel > lookup. > > Could you describe the issue in some more detail (e.g. when would you > see -EPROBE_DEFER here)? > > Johan
On Thu, May 04, 2023 at 10:38:54AM +0200, Johan Hovold wrote: > On Wed, May 03, 2023 at 08:13:54PM -0700, Bjorn Andersson wrote: > > On Tue, May 02, 2023 at 02:05:53PM +0200, Johan Hovold wrote: > > > On Mon, Apr 24, 2023 at 08:40:08PM -0700, Bjorn Andersson wrote: > > > > The QMP combo PHY sits in an of_graph connected between the DisplayPort > > > > controller and a USB Type-C connector (or possibly a redriver). > > > > > > > > The TCPM needs to be able to convey the HPD signal to the DisplayPort > > > > controller, but no directly link is provided by DeviceTree so the signal > > > > needs to "pass through" the QMP combo phy. > > > > > > > > Handle this by introducing a drm_bridge which upon initialization finds > > > > the next bridge (i.e. the usb-c-connector) and chain this together. This > > > > way HPD changes in the connector will propagate to the DisplayPort > > > > driver. > > > > > > > > The connector bridge is resolved lazily, as the TCPM is expected to be > > > > able to resolve the typec mux and switch at probe time, so the QMP combo > > > > phy will probe before the TCPM. > > > > > > > > Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com> > > > > --- > > > > drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 36 +++++++++++++++++++++++ > > > > 1 file changed, 36 insertions(+) > > > > > > > > diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > > > > index 5d6d6ef3944b..84bc08002537 100644 > > > > --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > > > > +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c > > > > > @@ -3196,6 +3200,34 @@ static int qmp_combo_register_clocks(struct qmp_combo *qmp, struct device_node * > > > > return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, dp_np); > > > > } > > > > > > > > +static int qmp_combo_bridge_attach(struct drm_bridge *bridge, > > > > + enum drm_bridge_attach_flags flags) > > > > +{ > > > > + struct qmp_combo *qmp = container_of(bridge, struct qmp_combo, bridge); > > > > + struct drm_bridge *next_bridge; > > > > + > > > > + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) > > > > + return -EINVAL; > > > > + > > > > + next_bridge = devm_drm_of_get_bridge(qmp->dev, qmp->dev->of_node, 0, 0); > > > > + if (IS_ERR(next_bridge)) > > > > + return dev_err_probe(qmp->dev, PTR_ERR(next_bridge), "failed to acquire drm_bridge\n"); > > > > > > Using dev_err_probe() in an attach callback looks wrong as these > > > functions should not be returning -EPROBE_DEFER (and this is not a probe > > > function). > > > > The problem is that this might return EPROBE_DEFER, and at least today > > propagates out to returning EPROBE_DEFER from our DP controller's > > bind(). > > Due to the known issue with the MSM driver panel lookup, or due to some > more fundamental problem with the stack? > No, but looks for the drm_bridge in the connector. > At least in the former case, I don't think we should hide the fact that > we have an unresolved issue with the MSM driver this way even if it > means printing an extra error message until it has been resolved (cf. > the panel lookup errors that we've intentionally kept in place). > > > This is not optimal, but unfortunately we have a two way dependency > > across the of_graph, so we need to make one of the sides lazy... > > But this comments seems to suggest this is a bigger issue than the panel > lookup. > > Could you describe the issue in some more detail (e.g. when would you > see -EPROBE_DEFER here)? > pmic_glink needs to look up the typec_switch_dev through the of_graph, which won't be present until the QMP phy is probed. And the QMP phy is looking for the connector, which won't be present until pmic_glink has found the QMP phy. So what I'm saying is that either pmic_glink or QMP needs to look up the other side lazily. The attach happens during bind of the msm_drm component, so at least today it's a consistent path to return EPROBE_DEFER in the DP controller... Regards, Bjorn
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index 5d6d6ef3944b..84bc08002537 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -22,6 +22,8 @@ #include <linux/usb/typec.h> #include <linux/usb/typec_mux.h> +#include <drm/drm_bridge.h> + #include <dt-bindings/phy/phy-qcom-qmp.h> #include "phy-qcom-qmp.h" @@ -1332,6 +1334,8 @@ struct qmp_combo { struct clk_hw dp_link_hw; struct clk_hw dp_pixel_hw; + struct drm_bridge bridge; + struct typec_switch_dev *sw; enum typec_orientation orientation; }; @@ -3196,6 +3200,34 @@ static int qmp_combo_register_clocks(struct qmp_combo *qmp, struct device_node * return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, dp_np); } +static int qmp_combo_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct qmp_combo *qmp = container_of(bridge, struct qmp_combo, bridge); + struct drm_bridge *next_bridge; + + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) + return -EINVAL; + + next_bridge = devm_drm_of_get_bridge(qmp->dev, qmp->dev->of_node, 0, 0); + if (IS_ERR(next_bridge)) + return dev_err_probe(qmp->dev, PTR_ERR(next_bridge), "failed to acquire drm_bridge\n"); + + return drm_bridge_attach(bridge->encoder, next_bridge, bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR); +} + +static const struct drm_bridge_funcs qmp_combo_bridge_funcs = { + .attach = qmp_combo_bridge_attach, +}; + +static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) +{ + qmp->bridge.funcs = &qmp_combo_bridge_funcs; + qmp->bridge.of_node = qmp->dev->of_node; + + return devm_drm_bridge_add(qmp->dev, &qmp->bridge); +} + static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_node *np) { struct device *dev = qmp->dev; @@ -3459,6 +3491,10 @@ static int qmp_combo_probe(struct platform_device *pdev) if (ret) return ret; + ret = qmp_combo_dp_register_bridge(qmp); + if (ret) + return ret; + /* Check for legacy binding with child nodes. */ usb_np = of_get_child_by_name(dev->of_node, "usb3-phy"); if (usb_np) {