From nobody Thu Oct 2 06:16:46 2025 Received: from smtpbgeu1.qq.com (smtpbgeu1.qq.com [52.59.177.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D2B53FBF0; Mon, 22 Sep 2025 01:21:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=52.59.177.22 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758504092; cv=none; b=VfdlRY0zhdCvS4JwiziJ2e96qPhE8ba3pwWLGkMLtqXlcRJ49geKm+LGPuSf1CNIlfap3lZeAhLaGxvYsTynn/xnYNfXeGVTCQ1e+mMX7fnYfQ9GRd6qKIVsPcvccoracOLfCdKiijaZbBb0CrZ5EeqVKpxV72ChiJ8IRLxMqlI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758504092; c=relaxed/simple; bh=VNlzQj1QA7KrRlDvHKmhJilhm6r3FZi6658RWY62J40=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=R3qQdxqjovgHzSLyYIsV4oos5xKEgUSgf7/tPGhOCv9O678ZwesW21FcB4iSPSXf9Im2UFAVWd5/MSFifhlxcxCpbNxOWMBbepIQTn2NO/BHTIsIFyOl/qkQGpOk/JX8Sn6JzsnPhzBtyxJ8QYNFZRGwyPIgHWIw9XLsfq++LnA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=airkyi.com; spf=pass smtp.mailfrom=airkyi.com; dkim=pass (1024-bit key) header.d=airkyi.com header.i=@airkyi.com header.b=eGX8cnF1; arc=none smtp.client-ip=52.59.177.22 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=airkyi.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=airkyi.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=airkyi.com header.i=@airkyi.com header.b="eGX8cnF1" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=airkyi.com; s=altu2504; t=1758504054; bh=LOGwnycc8Wj8KsW4WQRnp4T1oakm2MKzkiW7+jimOy4=; h=From:To:Subject:Date:Message-Id; b=eGX8cnF1nIcrrKoXzQyzKGc/E/lxgfHRUSnZrLMluvX/5GBq3nF7mOhhJVhts3v3I IYeKqyQRgt8aLUhBT0UIhv1oElNL5My5nSRjvf71us3VUiUDYW8LzqkIEHQVPSwhBU eMXIIT8fBDqcYvCreFjb1bCk/VZP8vh0YqwcM50g= X-QQ-mid: zesmtpgz1t1758504052td7dec9e0 X-QQ-Originating-IP: s3BHummt2O6hkB4Do51eRbWReEkBQZAIDj91AtlHJKk= Received: from DESKTOP-8BT1A2O.localdomain ( [58.22.7.114]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 22 Sep 2025 09:20:50 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 2496768016836932 From: Chaoyi Chen To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Vinod Koul , Kishon Vijay Abraham I , Heiko Stuebner , Sandy Huang , Andy Yan , Yubing Zhang , Frank Wang , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Amit Sunil Dhamne , Heikki Krogerus , Greg Kroah-Hartman , Chaoyi Chen , Dragan Simic , Johan Jonker , Diederik de Haas , Dmitry Baryshkov , Peter Robinson Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, dri-devel@lists.freedesktop.org Subject: [PATCH v4 1/7] usb: typec: Add default HPD device when register DisplayPort altmode Date: Mon, 22 Sep 2025 09:20:33 +0800 Message-Id: <20250922012039.323-2-kernel@airkyi.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20250922012039.323-1-kernel@airkyi.com> References: <20250922012039.323-1-kernel@airkyi.com> X-QQ-SENDSIZE: 520 Feedback-ID: zesmtpgz:airkyi.com:qybglogicsvrsz:qybglogicsvrsz4a-0 X-QQ-XMAILINFO: MZQHZNohqAr1d4b3kIdpe+C4sr2v02+KydlclYn3kPXkX9QWriwA44sZ tl6NjNtKounHPNhLPSgaBIec2LFNh3ZmJJtulRIlkzvCdAwxI5u3RspZ/EMJMZmzDZ6s+JK Us4iS1f3K21HNGZbVeTdh3ugbmCFdUHxqR85ZysIWazqHwUb6jo/a0gZPfEHlFxbFrHz8UD I8WzgpWaGSTdAi/CgA1KhpfPk0qKKQWBdhbz9sai/J2Ip7JDa6txxuKC3XP3UHQX9iqxdqt 0f6vZOIGljM75WywhPC8iBEs18/t6NM8EP82XyUBp6eU8+L7CrLRAqUYadN2bb+JdB1gNks C64UQoNCcYsMAlU/yS4rcfY3cOwXuqqpT5j9Cw4m0xJpHW+I0QNTUw/TepDP9YusbA26q0j W+JFXZPPGhAPA+u7PXAeBAI7ae9uJAEi6rlUJ0vi2AroTXruDhGrm4CcsT/TW6T+kLyVHq7 7Rd0D56UiB9hOcsuTvCB4nKZHkKc6F3yRq1h7jxoFeSty6c6zoS/Z/jrwjaZuwPDCrBkjTs zDuv/P+0PlcuCE4CQvdkpmnUcb4sm9HYKil0XR225xIqzEdVTuPnDp8JFqmHLOEYGQhccFQ l0wr5XGmemBzfu69c7h7j9CRIbOx3D8+zBlzL+NA6YwRz0VwJhwPjb0trMByPnvfacB0Sa0 Oy2gY+8jzEqwA+X5TFfh5aiVeMIFyvUfJAagvBK277oxbWOhBBGBUX7m9dJKUlmUz+ncMjG 4ZcsscGqxsE70Gr6ZfgPmFtyK/7EsCxxRQxhT1XV9ma9c85lsLpg0mbpr0n7uBwjojQbQQE +qh9vlOK2RhfJeKWgFOGR5fwSHynsDSpDdu89SPwvl3IfF5J+EoevaJlPa5EyHV427SwsvK gKHoNXL2qzWcdMBu+/E3hc3wqERWB9debQVmNRyUwf49s2SueY1OJSseiitEK4wLSYYK7wm SUK6sd+acr/gosoIG5X/R3WLzyMT70RcoQ2Fszg0M8eqXFQ== X-QQ-XMRINFO: Mp0Kj//9VHAxr69bL5MkOOs= X-QQ-RECHKSPAM: 0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Chaoyi Chen Add default DRM AUX HPD bridge device when register DisplayPort altmode. That makes it redundant for each Type-C driver to implement a similar registration process in embedded scenarios. Signed-off-by: Chaoyi Chen --- drivers/usb/typec/altmodes/displayport.c | 27 ++++++++++++++++++++++++ drivers/usb/typec/altmodes/displayport.h | 2 ++ drivers/usb/typec/class.c | 8 +++++++ include/linux/usb/typec_altmode.h | 2 ++ 4 files changed, 39 insertions(+) diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/a= ltmodes/displayport.c index 1dcb77faf85d..e026dc6e5430 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "displayport.h" =20 @@ -182,6 +183,10 @@ static int dp_altmode_status_update(struct dp_altmode = *dp) dp->pending_irq_hpd =3D true; } } else { + if (dp->port->hpd_dev) + drm_aux_hpd_bridge_notify(dp->port->hpd_dev, + hpd ? connector_status_connected : + connector_status_disconnected); drm_connector_oob_hotplug_event(dp->connector_fwnode, hpd ? connector_status_connected : connector_status_disconnected); @@ -206,6 +211,9 @@ static int dp_altmode_configured(struct dp_altmode *dp) * configuration is complete to signal HPD. */ if (dp->pending_hpd) { + if (dp->port->hpd_dev) + drm_aux_hpd_bridge_notify(dp->port->hpd_dev, + connector_status_connected); drm_connector_oob_hotplug_event(dp->connector_fwnode, connector_status_connected); sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); @@ -391,6 +399,9 @@ static int dp_altmode_vdm(struct typec_altmode *alt, dp->data.status =3D 0; dp->data.conf =3D 0; if (dp->hpd) { + if (dp->port->hpd_dev) + drm_aux_hpd_bridge_notify(dp->port->hpd_dev, + connector_status_disconnected); drm_connector_oob_hotplug_event(dp->connector_fwnode, connector_status_disconnected); dp->hpd =3D false; @@ -751,6 +762,18 @@ static const struct attribute_group *displayport_group= s[] =3D { NULL, }; =20 +void dp_altmode_hpd_device_register(struct typec_altmode *alt) +{ + if (alt->svid !=3D USB_TYPEC_DP_SID) + return; + + alt->hpd_dev =3D drm_dp_hpd_bridge_register(alt->dev.parent->parent, + dev_of_node(alt->dev.parent->parent)); + if (IS_ERR(alt->hpd_dev)) + alt->hpd_dev =3D NULL; +} +EXPORT_SYMBOL_GPL(dp_altmode_hpd_device_register); + int dp_altmode_probe(struct typec_altmode *alt) { const struct typec_altmode *port =3D typec_altmode_get_partner(alt); @@ -812,6 +835,10 @@ void dp_altmode_remove(struct typec_altmode *alt) cancel_work_sync(&dp->work); typec_altmode_put_plug(dp->plug_prime); =20 + if (dp->port->hpd_dev) + drm_aux_hpd_bridge_notify(dp->port->hpd_dev, + connector_status_disconnected); + if (dp->connector_fwnode) { drm_connector_oob_hotplug_event(dp->connector_fwnode, connector_status_disconnected); diff --git a/drivers/usb/typec/altmodes/displayport.h b/drivers/usb/typec/a= ltmodes/displayport.h index e120364da9fd..9f3483ec10fb 100644 --- a/drivers/usb/typec/altmodes/displayport.h +++ b/drivers/usb/typec/altmodes/displayport.h @@ -2,7 +2,9 @@ #if IS_ENABLED(CONFIG_TYPEC_DP_ALTMODE) int dp_altmode_probe(struct typec_altmode *alt); void dp_altmode_remove(struct typec_altmode *alt); +void dp_altmode_hpd_device_register(struct typec_altmode *alt); #else int dp_altmode_probe(struct typec_altmode *alt) { return -ENOTSUPP; } void dp_altmode_remove(struct typec_altmode *alt) { } +void dp_altmode_hpd_device_register(struct typec_altmode *alt) { } #endif /* CONFIG_TYPEC_DP_ALTMODE */ diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index 67a533e35150..95732b6d9a95 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -15,6 +15,7 @@ #include #include #include +#include "altmodes/displayport.h" =20 #include "bus.h" #include "class.h" @@ -600,6 +601,13 @@ typec_register_altmode(struct device *parent, return ERR_PTR(ret); } =20 + /* + * It is too late to register the HPD device when the DisplayPort + * altmode device becomes ready. If the current altmode is DP, + * register a static HPD device. + */ + dp_altmode_hpd_device_register(&alt->adev); + return &alt->adev; } =20 diff --git a/include/linux/usb/typec_altmode.h b/include/linux/usb/typec_al= tmode.h index b3c0866ea70f..acb0af1b9d5d 100644 --- a/include/linux/usb/typec_altmode.h +++ b/include/linux/usb/typec_altmode.h @@ -21,6 +21,7 @@ struct typec_altmode_ops; * @desc: Optional human readable description of the mode * @ops: Operations vector from the driver * @cable_ops: Cable operations vector from the driver. + * @hpd_dev: HPD device for DisplayPort */ struct typec_altmode { struct device dev; @@ -32,6 +33,7 @@ struct typec_altmode { char *desc; const struct typec_altmode_ops *ops; const struct typec_cable_ops *cable_ops; + struct device *hpd_dev; }; =20 #define to_typec_altmode(d) container_of(d, struct typec_altmode, dev) --=20 2.49.0 From nobody Thu Oct 2 06:16:46 2025 Received: from smtpbgbr1.qq.com (smtpbgbr1.qq.com [54.207.19.206]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D63981BC3F; Mon, 22 Sep 2025 01:21:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.207.19.206 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758504095; cv=none; b=tG3bZRKERXbvuvKEGlQZzmWc9kD04smfW7vn5DvWicz/N1kQdqKSGHs8GtuRECyZIwB4F71V8DcVfdpBmCXjNDCVmnaNN6DpmkejI52nJVIAO1fyM3HTffTGYeOhAk7BPy86rrp7w5OJX0QNngCS4GZlFQBs3OPmIHT1Luxw86c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758504095; c=relaxed/simple; bh=sP1d8X3yevNb1xdqh+ql3BXM5nEy5WWmG41uExBeCMs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=YHt9sso/De8+zbavcnZm1utkpdLcNTE4ZKBz03olh08Tr3HtRfmddBdS6fA3zimz6LgNShFxScpHcXLpYXOz/rzBROCMk2eiHaLrzbeaLPs6LpcC6O7DQ8Em6NuR8kA2lvCdjGk7YwyoRPTgaiMVVsCrBTFhcF2yu9i3IenigFQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=airkyi.com; spf=pass smtp.mailfrom=airkyi.com; dkim=pass (1024-bit key) header.d=airkyi.com header.i=@airkyi.com header.b=vfgidiCt; arc=none smtp.client-ip=54.207.19.206 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=airkyi.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=airkyi.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=airkyi.com header.i=@airkyi.com header.b="vfgidiCt" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=airkyi.com; s=altu2504; t=1758504058; bh=DH0kcIANYQpdYrJ+4fLx1mc6EkyYA+V45+fX1eNLgyY=; h=From:To:Subject:Date:Message-Id; b=vfgidiCtedzfWY6Rf6nANv0rffGgYakYjgrmxeVkzJOH3P7iVAlZdXwdoXf1MwixR Q84XJ57KZjYzvNBoTBsU81WYuD9TzxggbERw3A2z6yI0UEcfcZbV8YUuxM1DxzxBlI a84Yamqi629Z2XadfySsrt01Q+SldXrQ/eb7bofY= X-QQ-mid: zesmtpgz1t1758504056ta726d038 X-QQ-Originating-IP: qyExqdy1sQveIoLYmvNkfjq5s0h65cszYNtSFJabta4= Received: from DESKTOP-8BT1A2O.localdomain ( [58.22.7.114]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 22 Sep 2025 09:20:54 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 17474071139763469020 From: Chaoyi Chen To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Vinod Koul , Kishon Vijay Abraham I , Heiko Stuebner , Sandy Huang , Andy Yan , Yubing Zhang , Frank Wang , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Amit Sunil Dhamne , Heikki Krogerus , Greg Kroah-Hartman , Chaoyi Chen , Dragan Simic , Johan Jonker , Diederik de Haas , Dmitry Baryshkov , Peter Robinson Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, dri-devel@lists.freedesktop.org Subject: [PATCH v4 2/7] dt-bindings: phy: rockchip: rk3399-typec-phy: Support mode-switch Date: Mon, 22 Sep 2025 09:20:34 +0800 Message-Id: <20250922012039.323-3-kernel@airkyi.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20250922012039.323-1-kernel@airkyi.com> References: <20250922012039.323-1-kernel@airkyi.com> X-QQ-SENDSIZE: 520 Feedback-ID: zesmtpgz:airkyi.com:qybglogicsvrsz:qybglogicsvrsz4a-0 X-QQ-XMAILINFO: M1tjFO1fqc+0WDiZhGg+E3YIY9vFZWtMYby8sHj6P58TZfzMpsXHRKqp +N+pI3mAek2MS5eDsASBdXgWzfHaFqybvNBVm9d+7ry+gI9LsiBxERG7z4ScKqmRnD8rXkG pKrjybjwRbYm7qEsTYTRecoHs2sDTcmGAgjRMGPZkPM0Ma2o1mxtYTe3yWfEiBcBnOZbp0l qdeRudq7Odtva+uWZkcw0mRuudJDs8SWaqlFQRCkv8h9rlSQrmQVJ76lZ4lt0PEFyVunLZP lEtb+WawGOhvtYFuqwk3u8q0BB2R/8mfZAvvaGt6v9Fk8cqEykb51wG1lKZ0sPdUZYGRSI3 aaYnO0AyR4eGHSiWmW2874ompw35fo4mgE8Xwb07y4SPqBfGD0tQTows5WWGpSDmPsKPXAw QsCz91QxHp+gZF7JXC3D3QMcFRCNT/WqOShHq+O07pr/V6nkDGxnPQ7HT8TzINvj93RUZML BREIsH5jtiPYZ8tkIAI1bt/nHucDX0/1cfz/Cpz9Mcz4ZcgAFsjygeL8PcAXLSUBvNa/f8c JqmhS+b6k9X6F0rvMd1zy0MpaG1EMTisIyqaOptDM6PyDgMF9DMExwuD1W4T8HGateUycTX OkyKQanioFkDL1nBSX/sjjt+u3lZ9SfAZ5gHT12mnoNgCxwqkeUsXN3NLp4YyQ2h3qprVcL J4ZY/Rc6XjCEPsi2UueLp2rMgB1ulHweqtGrLJEw2sjiNQRnz1CBghHGs+5WfwyENxh+0ax JSM86Goah3oWwfAE52kTItfzArpkEjAvcCTz2S93cvOqOHYnCMQzti7nsG3HvIvn6DvrdR+ GXVzVeT2JG3ae0SCKqv0fSL9WcJ61zQ6b23+w8F5D6RD3Q/6edYFYKZjpt3W9SVRuY5rgqk YC4Uslk/KlkUrlZY47iPqRI/DhpfJr4UrQaRHuMlcC8uZ6MemLjDL8ahw8g0RjDjEZFn6Q1 XdfVFrHatPK2bfrtAHl2IYCe2sFUpx+l5QMlJ4tVsOoOC4gvkxpR7tgG+i41+l39kvgfe1t /VfPxO0g== X-QQ-XMRINFO: Mp0Kj//9VHAxr69bL5MkOOs= X-QQ-RECHKSPAM: 0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Chaoyi Chen The RK3399 SoC integrates two USB/DP combo PHYs, each of which supports software-configurable pin mapping and DisplayPort lane assignment. These capabilities enable the PHY itself to handle both mode switching and orientation switching, based on the Type-C plug orientation and USB PD negotiation results. While an external Type-C controller is still required to detect cable attachment and report USB PD events, the actual mode and orientation switching is performed internally by the PHY through software configuration. This allows the PHY to act as a Type-C multiplexer for both data role and DP altmode configuration. To reflect this hardware design, this patch introduces a new "mode-switch" property for the dp-port node in the device tree bindings. This property indicates that the connected PHY is capable of handling Type-C mode switching itself. Signed-off-by: Chaoyi Chen Acked-by: Krzysztof Kozlowski --- Changes in v4: - Remove "|" in description. Changes in v3: - Add more descriptions to clarify the role of the PHY in switching. Changes in v2: - Reuse dp-port/usb3-port in rk3399-typec-phy binding. .../devicetree/bindings/phy/rockchip,rk3399-typec-phy.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/phy/rockchip,rk3399-typec-ph= y.yaml b/Documentation/devicetree/bindings/phy/rockchip,rk3399-typec-phy.ya= ml index 91c011f68cd0..83ebcde096ea 100644 --- a/Documentation/devicetree/bindings/phy/rockchip,rk3399-typec-phy.yaml +++ b/Documentation/devicetree/bindings/phy/rockchip,rk3399-typec-phy.yaml @@ -51,6 +51,12 @@ properties: '#phy-cells': const: 0 =20 + mode-switch: + description: + Indicates the PHY can handle altmode switching. In this case, + requires an external USB Type-C controller to report USB PD mess= age. + type: boolean + port: $ref: /schemas/graph.yaml#/properties/port description: Connection to USB Type-C connector --=20 2.49.0 From nobody Thu Oct 2 06:16:46 2025 Received: from smtpbguseast3.qq.com (smtpbguseast3.qq.com [54.243.244.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 763681A238C; Mon, 22 Sep 2025 01:21:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.243.244.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758504100; cv=none; b=LQFcGfAz0pZr40MzjE+MZ7kZKIOhea2kQ/AeWb5CrSmNe8MaLvonKpkr0zR5PUQvMykagOUs3ZqzFl/XIaJRR8vp6ipEWEFKtHd4yhRdWc9tnusR6h5J2fTfivXqotHdzYZs4IwTZrlK8keG2SokmDzRSfIrBtTD11bTVruiGe0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758504100; c=relaxed/simple; bh=IcvTUrbIvNOoPPpd9K3Np+W4YNpuoY6nyIadwQJf7os=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=sDtKQz4Y2AYya4qj2oyIC/AjnVM+gcl6MHagfj5WpFEhPOhIdULxBEOV4g7VYkoCnK66btxQ4738kJ6+qGNZPcob1z9P9tmSrFmwfDql/bxGjKpVu/lA65QHaMv6fYDo1c1ewID1jHphhEgxlgM9ubNES45LKWppqnQRQ3NCYI0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=airkyi.com; spf=pass smtp.mailfrom=airkyi.com; dkim=pass (1024-bit key) header.d=airkyi.com header.i=@airkyi.com header.b=JmZ/zCQA; arc=none smtp.client-ip=54.243.244.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=airkyi.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=airkyi.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=airkyi.com header.i=@airkyi.com header.b="JmZ/zCQA" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=airkyi.com; s=altu2504; t=1758504061; bh=Yi6bUqe5/vcuqvz2KYqLsQmo/crbod6X+jkr/5OlqM4=; h=From:To:Subject:Date:Message-Id; b=JmZ/zCQAVX2+q/TSSNo4kCMLEgUETkdk79bBJJDRzdMjUFhwJuA94zPcUGN1WxQEH rrTa5/bH5z+wcxUdimhI/0jl/2NUzNAHxp4r5LvzSRXkXMpB8Qd0W65PnRi3q4lEnX JiOsQMNoe2+uniedH83MOZup+owQ6BkQ97mtmNf4= X-QQ-mid: zesmtpgz1t1758504060t1dfe59a4 X-QQ-Originating-IP: 8yTSZt1ezK9BOZQXMQ9fRUQoLbip3wSV0d9Poaekz2E= Received: from DESKTOP-8BT1A2O.localdomain ( [58.22.7.114]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 22 Sep 2025 09:20:57 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 14631667019847014216 From: Chaoyi Chen To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Vinod Koul , Kishon Vijay Abraham I , Heiko Stuebner , Sandy Huang , Andy Yan , Yubing Zhang , Frank Wang , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Amit Sunil Dhamne , Heikki Krogerus , Greg Kroah-Hartman , Chaoyi Chen , Dragan Simic , Johan Jonker , Diederik de Haas , Dmitry Baryshkov , Peter Robinson Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, dri-devel@lists.freedesktop.org Subject: [PATCH v4 3/7] phy: rockchip: phy-rockchip-typec: Add typec_mux/typec_switch support Date: Mon, 22 Sep 2025 09:20:35 +0800 Message-Id: <20250922012039.323-4-kernel@airkyi.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20250922012039.323-1-kernel@airkyi.com> References: <20250922012039.323-1-kernel@airkyi.com> X-QQ-SENDSIZE: 520 Feedback-ID: zesmtpgz:airkyi.com:qybglogicsvrsz:qybglogicsvrsz4a-0 X-QQ-XMAILINFO: NQR8mRxMnur9Dz0IxYz/h+G9CrCkGShU72VYcsAFYMIYacwEuI79twhB pKCPfVDsICXK/k3GrZzKijwnxxVB310vSxoCqx56nAhNBLGh37QOhZ5khPferubj3qBjDjg 2oP9EQKQ3AataSMzHQq67pTG5H2KwQALvgNxxtpmVGcS4XFeMcwfYgQml5KIfdQcq1erMvg Z8QhP8geKglLOxABHbpKWZESZx1jVZ+5DkTBh6bzoX8u3sSX+pSabTAv+9EFeALm0AKF7cc RXMIjrH+Aiz9euRi7NESerMO7EuOsXjXltNfzkwxglcMuTxe0OoLxjo6LjBHwvdgC5Dw9mA qiIk1hXD8vGCz4n2KfLkE+thxcqFtLfeDr/7Pn915LhgoVWLK9Qzi4KghKnbwkzfY59/2HB LvjdkebPYsQIglNjo96KfqaE04pY2YCBJ3x8JovGhyTRurU3qyynovdM4DalztY/ou2LB3a YEf1YbbUcF7UZ5OtsUbmC9vRU2YvfmvJR8vsU90AW8jby38OXrIo9PJE1F52BPlIomhjzTI RZqGhz+eHOqupzUj3KEihSkYwNqvY9WAMBUveBsjOXjUoiGDYFExRX0Q3fIFX8CtSNzU0Hi TTplkSYXJDi0rVctOGxuHPVWdpsPUmb2lF3WozfkeTWj2soE6+MLK1SmqPzZDWH7EkyOmYm YeUaBBE0Fu8QC4fDGuGgd6Bm4V22X7JOTtVo83CRa1WLTLFoXQ4+3EVDB6jtuHWtKTkDwUI diZhtZdVxggBDt40ngOgnOWaZQj8Dxk0Ai0v1SoxmIqg9MiGkOquPfagDFOfPtq1YRgTo5C LGzcQG7KPejfxJHORtKJaqIMa+Vhsdu73lgR7nz2Vn+MyPBpVCzCqtZzjdflxZElHM3Gc1/ zGM9R7C/TI7g8EcfMyaYjSbj6ZWnd3Krh5cRMV+8QDvjt1yx+aYkaUbs61lEskvmH+lOvmO 82rIypOZxfI24SAdwTIwWTLAGNtZKDPpsBBXcrq29r+vghuSezEE+dSDRYocJyutrfqUUfK RIem8Nww== X-QQ-XMRINFO: Mp0Kj//9VHAxr69bL5MkOOs= X-QQ-RECHKSPAM: 0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Chaoyi Chen This patch add support for Type-C Port Controller Manager. Each PHY will register typec_mux and typec_switch when external Type-C controller is present. Type-C events are handled by TCPM without extcon. The extcon device should still be supported. Signed-off-by: Chaoyi Chen --- Changes in v4: - Remove notify DP HPD state by USB/DP PHY. (no changes since v3) Changes in v2: - Fix compile error when CONFIG_TYPEC is not enabled. - Notify DP HPD state by USB/DP PHY. drivers/phy/rockchip/phy-rockchip-typec.c | 365 +++++++++++++++++++++- 1 file changed, 349 insertions(+), 16 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockch= ip/phy-rockchip-typec.c index d9701b6106d5..4a1dfa8d65c7 100644 --- a/drivers/phy/rockchip/phy-rockchip-typec.c +++ b/drivers/phy/rockchip/phy-rockchip-typec.c @@ -54,6 +54,8 @@ =20 #include #include +#include +#include =20 #define CMN_SSM_BANDGAP (0x21 << 2) #define CMN_SSM_BIAS (0x22 << 2) @@ -286,12 +288,23 @@ #define RX_DIAG_SC2C_DELAY (0x81e1 << 2) =20 #define PMA_LANE_CFG (0xc000 << 2) +#define PMA_LANE3_DP_LANE_SEL(x) (((x) & 0x3) << 14) +#define PMA_LANE3_INTERFACE_SEL(x) (((x) & 0x1) << 12) +#define PMA_LANE2_DP_LANE_SEL(x) (((x) & 0x3) << 10) +#define PMA_LANE2_INTERFACE_SEL(x) (((x) & 0x1) << 8) +#define PMA_LANE1_DP_LANE_SEL(x) (((x) & 0x3) << 6) +#define PMA_LANE1_INTERFACE_SEL(x) (((x) & 0x1) << 4) +#define PMA_LANE0_DP_LANE_SEL(x) (((x) & 0x3) << 2) +#define PMA_LANE0_INTERFACE_SEL(x) (((x) & 0x1) << 0) #define PIPE_CMN_CTRL1 (0xc001 << 2) #define PIPE_CMN_CTRL2 (0xc002 << 2) #define PIPE_COM_LOCK_CFG1 (0xc003 << 2) #define PIPE_COM_LOCK_CFG2 (0xc004 << 2) #define PIPE_RCV_DET_INH (0xc005 << 2) #define DP_MODE_CTL (0xc008 << 2) +#define PHY_DP_POWER_STATE_ACK_MASK GENMASK(7, 4) +#define PHY_DP_POWER_STATE_ACK_SHIFT 4 +#define PHY_DP_POWER_STATE_MASK GENMASK(3, 0) #define DP_CLK_CTL (0xc009 << 2) #define STS (0xc00F << 2) #define PHY_ISO_CMN_CTRL (0xc010 << 2) @@ -327,8 +340,15 @@ =20 #define DP_MODE_A0 BIT(4) #define DP_MODE_A2 BIT(6) -#define DP_MODE_ENTER_A0 0xc101 -#define DP_MODE_ENTER_A2 0xc104 + +#define DP_MODE_MASK 0xf +#define DP_MODE_ENTER_A0 BIT(0) +#define DP_MODE_ENTER_A2 BIT(2) +#define DP_MODE_ENTER_A3 BIT(3) +#define DP_MODE_A0_ACK BIT(4) +#define DP_MODE_A2_ACK BIT(6) +#define DP_MODE_A3_ACK BIT(7) +#define DP_LINK_RESET_DEASSERTED BIT(8) =20 #define PHY_MODE_SET_TIMEOUT 100000 =20 @@ -340,6 +360,31 @@ #define MODE_DFP_USB BIT(1) #define MODE_DFP_DP BIT(2) =20 +enum phy_dp_lane_num { + PHY_DP_LANE_0 =3D 0, + PHY_DP_LANE_1, + PHY_DP_LANE_2, + PHY_DP_LANE_3, +}; + +enum phy_pma_if { + PMA_IF_PIPE_PCS =3D 0, + PMA_IF_PHY_DP, +}; + +enum phy_typec_role { + TYPEC_PHY_USB =3D 0, + TYPEC_PHY_DP, + TYPEC_PHY_MAX, +}; + +enum phy_dp_power_state { + PHY_DP_POWER_STATE_A0 =3D 0, + PHY_DP_POWER_STATE_A1, + PHY_DP_POWER_STATE_A2, + PHY_DP_POWER_STATE_A3, +}; + struct usb3phy_reg { u32 offset; u32 enable_bit; @@ -372,18 +417,22 @@ struct rockchip_typec_phy { struct device *dev; void __iomem *base; struct extcon_dev *extcon; + struct typec_mux_dev *mux; + struct typec_switch_dev *sw; struct regmap *grf_regs; struct clk *clk_core; struct clk *clk_ref; struct reset_control *uphy_rst; struct reset_control *pipe_rst; struct reset_control *tcphy_rst; + struct phy *phys[TYPEC_PHY_MAX]; const struct rockchip_usb3phy_port_cfg *port_cfgs; /* mutex to protect access to individual PHYs */ struct mutex lock; =20 bool flip; u8 mode; + u8 new_mode; }; =20 struct phy_reg { @@ -454,6 +503,99 @@ static const struct rockchip_usb3phy_port_cfg rk3399_u= sb3phy_port_cfgs[] =3D { { /* sentinel */ } }; =20 +static int tcphy_cfg_usb3_to_usb2_only(struct rockchip_typec_phy *tcphy, + bool value); + +static int tcphy_dp_set_power_state(struct rockchip_typec_phy *tcphy, + enum phy_dp_power_state state) +{ + u32 ack, reg, sts =3D BIT(state); + int ret; + + /* + * Power state changes must not be requested until after the cmn_ready + * signal has gone active. + */ + reg =3D readl(tcphy->base + PMA_CMN_CTRL1); + if (!(reg & CMN_READY)) { + dev_err(tcphy->dev, "cmn_ready in the inactive state\n"); + return -EINVAL; + } + + reg =3D readl(tcphy->base + DP_MODE_CTL); + reg &=3D ~PHY_DP_POWER_STATE_MASK; + reg |=3D sts; + writel(reg, tcphy->base + DP_MODE_CTL); + + ret =3D readl_poll_timeout(tcphy->base + DP_MODE_CTL, + ack, (((ack & PHY_DP_POWER_STATE_ACK_MASK) >> + PHY_DP_POWER_STATE_ACK_SHIFT) =3D=3D sts), 10, + PHY_MODE_SET_TIMEOUT); + if (ret < 0) { + dev_err(tcphy->dev, "failed to enter power state %d\n", state); + return ret; + } + + return 0; +} + +/* + * For the TypeC PHY, the 4 lanes are mapping to the USB TypeC receptacle = pins + * as follows: + * ------------------------------------------------------------------- + * PHY Lanes/Module Pins TypeC Receptacle Pins + * ------------------------------------------------------------------- + * Lane0 (tx_p/m_ln_0) TX1+/TX1- (pins A2/A3) + * Lane1 (tx_rx_p/m_ln_1) RX1+/RX1- (pins B11/B10) + * Lane2 (tx_rx_p/m_ln_2) RX2+/RX2- (pins A11/A10) + * Lane3 (tx_p/m_ln_3) TX2+/TX2- (pins B2/B3) + * ------------------------------------------------------------------- + * + * USB and DP lanes mapping to TypeC PHY lanes for each of pin assignment + * options (normal connector orientation) described in the VESA DisplayPort + * Alt Mode on USB TypeC Standard as follows: + * + * ---------------------------------------------------------------------- + * PHY Lanes A B C D E F + * ---------------------------------------------------------------------- + * 0 ML1 SSTX ML2 SSTX ML2 SSTX + * 1 ML3 SSRX ML3 SSRX ML3 SSRX + * 2 ML2 ML1 ML0 ML0 ML0 ML0 + * 3 ML0 ML0 ML1 ML1 ML1 ML1 + * ---------------------------------------------------------------------- + */ +static void tcphy_set_lane_mapping(struct rockchip_typec_phy *tcphy, u8 mo= de) +{ + /* + * The PMA_LANE_CFG register is used to select whether a PMA lane + * is mapped for USB or PHY DP. The PMA_LANE_CFG register is + * configured based on a normal connector orientation. Logic in the + * PHY automatically handles the flipped connector case based on the + * setting of orientation of TypeC PHY. + */ + if (mode =3D=3D MODE_DFP_DP) { + /* This maps to VESA DP Alt Mode pin assignments C and E. */ + writel(PMA_LANE3_DP_LANE_SEL(PHY_DP_LANE_1) | + PMA_LANE3_INTERFACE_SEL(PMA_IF_PHY_DP) | + PMA_LANE2_DP_LANE_SEL(PHY_DP_LANE_0) | + PMA_LANE2_INTERFACE_SEL(PMA_IF_PHY_DP) | + PMA_LANE1_DP_LANE_SEL(PHY_DP_LANE_3) | + PMA_LANE1_INTERFACE_SEL(PMA_IF_PHY_DP) | + PMA_LANE0_DP_LANE_SEL(PHY_DP_LANE_2) | + PMA_LANE0_INTERFACE_SEL(PMA_IF_PHY_DP), + tcphy->base + PMA_LANE_CFG); + } else { + /* This maps to VESA DP Alt Mode pin assignments D and F. */ + writel(PMA_LANE3_DP_LANE_SEL(PHY_DP_LANE_1) | + PMA_LANE3_INTERFACE_SEL(PMA_IF_PHY_DP) | + PMA_LANE2_DP_LANE_SEL(PHY_DP_LANE_0) | + PMA_LANE2_INTERFACE_SEL(PMA_IF_PHY_DP) | + PMA_LANE1_INTERFACE_SEL(PMA_IF_PIPE_PCS) | + PMA_LANE0_INTERFACE_SEL(PMA_IF_PIPE_PCS), + tcphy->base + PMA_LANE_CFG); + } +} + static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy) { u32 i, rdata; @@ -743,8 +885,10 @@ static int tcphy_phy_init(struct rockchip_typec_phy *t= cphy, u8 mode) tcphy_dp_aux_set_flip(tcphy); =20 tcphy_cfg_24m(tcphy); + tcphy_set_lane_mapping(tcphy, mode); =20 if (mode =3D=3D MODE_DFP_DP) { + tcphy_cfg_usb3_to_usb2_only(tcphy, true); tcphy_cfg_dp_pll(tcphy); for (i =3D 0; i < 4; i++) tcphy_dp_cfg_lane(tcphy, i); @@ -768,7 +912,10 @@ static int tcphy_phy_init(struct rockchip_typec_phy *t= cphy, u8 mode) writel(PIN_ASSIGN_D_F, tcphy->base + PMA_LANE_CFG); } =20 - writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL); + val =3D readl(tcphy->base + DP_MODE_CTL); + val &=3D ~DP_MODE_MASK; + val |=3D DP_MODE_ENTER_A2 | DP_LINK_RESET_DEASSERTED; + writel(val, tcphy->base + DP_MODE_CTL); =20 reset_control_deassert(tcphy->uphy_rst); =20 @@ -811,8 +958,9 @@ static int tcphy_get_mode(struct rockchip_typec_phy *tc= phy) u8 mode; int ret, ufp, dp; =20 + /* If extcon not exist, try to use tcpm mode */ if (!edev) - return MODE_DFP_USB; + return tcphy->new_mode; =20 ufp =3D extcon_get_state(edev, EXTCON_USB); dp =3D extcon_get_state(edev, EXTCON_DISP_DP); @@ -850,6 +998,72 @@ static int tcphy_get_mode(struct rockchip_typec_phy *t= cphy) return mode; } =20 +#if IS_ENABLED(CONFIG_TYPEC) +static int tcphy_orien_sw_set(struct typec_switch_dev *sw, + enum typec_orientation orien) +{ + struct rockchip_typec_phy *tcphy =3D typec_switch_get_drvdata(sw); + + mutex_lock(&tcphy->lock); + + if (orien =3D=3D TYPEC_ORIENTATION_NONE) { + tcphy->new_mode =3D MODE_DISCONNECT; + goto unlock_ret; + } + + tcphy->flip =3D (orien =3D=3D TYPEC_ORIENTATION_REVERSE) ? true : false; + tcphy->new_mode =3D MODE_DFP_USB; + +unlock_ret: + mutex_unlock(&tcphy->lock); + return 0; +} + +static void udphy_orien_switch_unregister(void *data) +{ + struct rockchip_typec_phy *tcphy =3D data; + + typec_switch_unregister(tcphy->sw); +} + +static int tcphy_setup_orien_switch(struct rockchip_typec_phy *tcphy) +{ + struct typec_switch_desc sw_desc =3D { }; + struct device_node *np; + int ret =3D 0; + + np =3D of_get_child_by_name(tcphy->dev->of_node, "usb3-port"); + if (!np) + return 0; + + if (!of_property_read_bool(np, "orientation-switch")) + goto put_np; + + sw_desc.drvdata =3D tcphy; + sw_desc.fwnode =3D device_get_named_child_node(tcphy->dev, "usb3-port"); + sw_desc.set =3D tcphy_orien_sw_set; + + tcphy->sw =3D typec_switch_register(tcphy->dev, &sw_desc); + if (IS_ERR(tcphy->sw)) { + dev_err(tcphy->dev, "Error register typec orientation switch: %ld\n", + PTR_ERR(tcphy->sw)); + ret =3D PTR_ERR(tcphy->sw); + goto put_np; + } + + ret =3D devm_add_action_or_reset(tcphy->dev, udphy_orien_switch_unregiste= r, tcphy); + +put_np: + of_node_put(np); + return ret; +} +#else +static int tcphy_setup_orien_switch(struct rockchip_typec_phy *tcphy) +{ + return 0; +} +#endif + static int tcphy_cfg_usb3_to_usb2_only(struct rockchip_typec_phy *tcphy, bool value) { @@ -989,14 +1203,9 @@ static int rockchip_dp_phy_power_on(struct phy *phy) =20 tcphy_dp_aux_calibration(tcphy); =20 - writel(DP_MODE_ENTER_A0, tcphy->base + DP_MODE_CTL); - - ret =3D readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL, - val, val & DP_MODE_A0, 1000, - PHY_MODE_SET_TIMEOUT); - if (ret < 0) { - writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL); - dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n"); + ret =3D tcphy_dp_set_power_state(tcphy, PHY_DP_POWER_STATE_A0); + if (ret) { + dev_err(tcphy->dev, "failed to enter A0 power state\n"); goto power_on_finish; } =20 @@ -1013,6 +1222,7 @@ static int rockchip_dp_phy_power_on(struct phy *phy) static int rockchip_dp_phy_power_off(struct phy *phy) { struct rockchip_typec_phy *tcphy =3D phy_get_drvdata(phy); + int ret; =20 mutex_lock(&tcphy->lock); =20 @@ -1021,7 +1231,11 @@ static int rockchip_dp_phy_power_off(struct phy *phy) =20 tcphy->mode &=3D ~MODE_DFP_DP; =20 - writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL); + ret =3D tcphy_dp_set_power_state(tcphy, PHY_DP_POWER_STATE_A2); + if (ret) { + dev_err(tcphy->dev, "failed to enter A2 power state\n"); + goto unlock; + } =20 if (tcphy->mode =3D=3D MODE_DISCONNECT) tcphy_phy_deinit(tcphy); @@ -1037,6 +1251,89 @@ static const struct phy_ops rockchip_dp_phy_ops =3D { .owner =3D THIS_MODULE, }; =20 +#if IS_ENABLED(CONFIG_TYPEC) +static int tcphy_typec_mux_set(struct typec_mux_dev *mux, struct typec_mux= _state *state) +{ + struct rockchip_typec_phy *tcphy =3D typec_mux_get_drvdata(mux); + struct typec_displayport_data *data; + int hpd =3D 0; + + mutex_lock(&tcphy->lock); + + switch (state->mode) { + case TYPEC_STATE_SAFE: + fallthrough; + case TYPEC_STATE_USB: + tcphy->new_mode =3D MODE_DFP_USB; + phy_set_bus_width(tcphy->phys[TYPEC_PHY_DP], 0); + break; + case TYPEC_DP_STATE_C: + case TYPEC_DP_STATE_E: + tcphy->new_mode =3D MODE_DFP_DP; + data =3D state->data; + hpd =3D !!(data->status & DP_STATUS_HPD_STATE); + phy_set_bus_width(tcphy->phys[TYPEC_PHY_DP], hpd ? 4 : 0); + break; + case TYPEC_DP_STATE_D: + tcphy->new_mode =3D MODE_DFP_DP | MODE_DFP_USB; + data =3D state->data; + hpd =3D !!(data->status & DP_STATUS_HPD_STATE); + phy_set_bus_width(tcphy->phys[TYPEC_PHY_DP], hpd ? 2 : 0); + break; + default: + break; + } + + mutex_unlock(&tcphy->lock); + + return 0; +} + +static void tcphy_typec_mux_unregister(void *data) +{ + struct rockchip_typec_phy *tcphy =3D data; + + typec_mux_unregister(tcphy->mux); +} + +static int tcphy_setup_typec_mux(struct rockchip_typec_phy *tcphy) +{ + struct typec_mux_desc mux_desc =3D {}; + struct device_node *np; + int ret =3D 0; + + np =3D of_get_child_by_name(tcphy->dev->of_node, "dp-port"); + if (!np) + return 0; + + if (!of_property_read_bool(np, "mode-switch")) + goto put_np; + + mux_desc.drvdata =3D tcphy; + mux_desc.fwnode =3D device_get_named_child_node(tcphy->dev, "dp-port"); + mux_desc.set =3D tcphy_typec_mux_set; + + tcphy->mux =3D typec_mux_register(tcphy->dev, &mux_desc); + if (IS_ERR(tcphy->mux)) { + dev_err(tcphy->dev, "Error register typec mux: %ld\n", + PTR_ERR(tcphy->mux)); + ret =3D PTR_ERR(tcphy->mux); + goto put_np; + } + + ret =3D devm_add_action_or_reset(tcphy->dev, tcphy_typec_mux_unregister, = tcphy); + +put_np: + of_node_put(np); + return ret; +} +#else +static int tcphy_setup_typec_mux(struct rockchip_typec_phy *tcphy) +{ + return 0; +} +#endif + static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy, struct device *dev) { @@ -1095,6 +1392,25 @@ static void typec_phy_pre_init(struct rockchip_typec= _phy *tcphy) tcphy->mode =3D MODE_DISCONNECT; } =20 +static int typec_dp_lane_get(struct rockchip_typec_phy *tcphy) +{ + int dp_lanes; + + switch (tcphy->new_mode) { + case MODE_DFP_DP: + dp_lanes =3D 4; + break; + case MODE_DFP_DP | MODE_DFP_USB: + dp_lanes =3D 2; + break; + default: + dp_lanes =3D 0; + break; + } + + return dp_lanes; +} + static int rockchip_typec_phy_probe(struct platform_device *pdev) { struct device *dev =3D &pdev->dev; @@ -1142,6 +1458,7 @@ static int rockchip_typec_phy_probe(struct platform_d= evice *pdev) return ret; =20 tcphy->dev =3D dev; + tcphy->new_mode =3D MODE_DFP_USB; platform_set_drvdata(pdev, tcphy); mutex_init(&tcphy->lock); =20 @@ -1151,6 +1468,7 @@ static int rockchip_typec_phy_probe(struct platform_d= evice *pdev) if (IS_ERR(tcphy->extcon)) { if (PTR_ERR(tcphy->extcon) =3D=3D -ENODEV) { tcphy->extcon =3D NULL; + dev_info(dev, "extcon not exist, try to use typec mux\n"); } else { if (PTR_ERR(tcphy->extcon) !=3D -EPROBE_DEFER) dev_err(dev, "Invalid or missing extcon\n"); @@ -1158,19 +1476,34 @@ static int rockchip_typec_phy_probe(struct platform= _device *pdev) } } =20 + ret =3D tcphy_setup_orien_switch(tcphy); + if (ret) + return ret; + + ret =3D tcphy_setup_typec_mux(tcphy); + if (ret) + return ret; + pm_runtime_enable(dev); =20 for_each_available_child_of_node(np, child_np) { struct phy *phy; =20 - if (of_node_name_eq(child_np, "dp-port")) + if (of_node_name_eq(child_np, "dp-port")) { phy =3D devm_phy_create(dev, child_np, &rockchip_dp_phy_ops); - else if (of_node_name_eq(child_np, "usb3-port")) + if (!IS_ERR(phy)) { + tcphy->phys[TYPEC_PHY_DP] =3D phy; + phy_set_bus_width(phy, typec_dp_lane_get(tcphy)); + } + } else if (of_node_name_eq(child_np, "usb3-port")) { phy =3D devm_phy_create(dev, child_np, &rockchip_usb3_phy_ops); - else + if (!IS_ERR(phy)) + tcphy->phys[TYPEC_PHY_USB] =3D phy; + } else { continue; + } =20 if (IS_ERR(phy)) { dev_err(dev, "failed to create phy: %pOFn\n", --=20 2.49.0 From nobody Thu Oct 2 06:16:46 2025 Received: from smtpbgjp3.qq.com (smtpbgjp3.qq.com [54.92.39.34]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 04B7A17332C; Mon, 22 Sep 2025 01:21:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.92.39.34 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758504096; cv=none; b=d7o2cLb4cs+K/kn9l3YhoBZM28iCH/f3v2DNRsT2hva7Jz67EwinCQ21ARC4MQCYdGDeA1ZP9NJwFi60H5GTycTFL+QK8ZA1wEBWEdzfNExY+0ZYCZfblRuR9DJr2xVr8bUDQ0z0u2HwS+IUn4wPE2MwPfO9QSNralGWdCB34so= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758504096; c=relaxed/simple; bh=u8Zr+mWZOjLQIv8KovRN/165RoC4n1Ipx2xQvrNpJpc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=RQhzld6FdtUh6eEaBRZHaqYbgA/pl8Pfakk8dQyJopFef5atOrGkTwni4HagefklspkfHTFdYUc018eaPqWjD4K44jE9tpbGmdKlRKqSp49OMvXIojClcBeMDvc4ySC+C2EuRSyxfsTFAWZlrio+EQ0r+WB8IYqRtsHBra1+A/Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=airkyi.com; spf=pass smtp.mailfrom=airkyi.com; dkim=pass (1024-bit key) header.d=airkyi.com header.i=@airkyi.com header.b=hp5OAXZn; arc=none smtp.client-ip=54.92.39.34 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=airkyi.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=airkyi.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=airkyi.com header.i=@airkyi.com header.b="hp5OAXZn" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=airkyi.com; s=altu2504; t=1758504065; bh=bU2sAmzXCR713CrWSoUTQXsce2x0+sMC5yQVrxIUCRM=; h=From:To:Subject:Date:Message-Id; b=hp5OAXZnfvcYiEOnalIQqkanqol5thjeWSEc3caa+ilFkfSMFi0r4Wp8j8gh5mfAj +N9MeNwucQMVlA8zwkoVM+RzUQiXFd7zcVD0V1xyQjq+7cml19YrZuycIPHrvTCCC3 5UBnR9m6YilgTP3jNOFU5kmh5WSmYkDt73284U7M= X-QQ-mid: zesmtpgz1t1758504063t10fb6b9b X-QQ-Originating-IP: DDHFghLsHmSB71st719yB2ojgwG4K8hbUJVFjP+vjd8= Received: from DESKTOP-8BT1A2O.localdomain ( [58.22.7.114]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 22 Sep 2025 09:21:01 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 17509678942044025662 From: Chaoyi Chen To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Vinod Koul , Kishon Vijay Abraham I , Heiko Stuebner , Sandy Huang , Andy Yan , Yubing Zhang , Frank Wang , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Amit Sunil Dhamne , Heikki Krogerus , Greg Kroah-Hartman , Chaoyi Chen , Dragan Simic , Johan Jonker , Diederik de Haas , Dmitry Baryshkov , Peter Robinson Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, dri-devel@lists.freedesktop.org Subject: [PATCH v4 4/7] drm/rockchip: cdn-dp: Support handle lane info without extcon Date: Mon, 22 Sep 2025 09:20:36 +0800 Message-Id: <20250922012039.323-5-kernel@airkyi.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20250922012039.323-1-kernel@airkyi.com> References: <20250922012039.323-1-kernel@airkyi.com> X-QQ-SENDSIZE: 520 Feedback-ID: zesmtpgz:airkyi.com:qybglogicsvrsz:qybglogicsvrsz4a-0 X-QQ-XMAILINFO: OB07sFyS3L6p+Qvod07WZ2wWVQ3R2+r1sYbsl6Xuc1dBkdjKARRQs5S0 msulJV0mEe4uDQL0gRbm/EKE9W14yHcdfCA35KiEzPcbv4kFjLpXIO5kRRvrLtX3+QaB6Do TH7IwhbE01khFAH9IUGFDMpKGPBDfgACbDQHGfCIEHxHKDGdZKc+8zeD0AVhA/GmAxqwDd0 Poq9+cwa+ZRm/vuOh7CV+JkKFVoy1ilas+5ZaXJ9YSlSfe8YPUT+btUXTrxPBeNQGB/7bti ifxgStCaxnsZTmgxwYnlzdBefr4umCQuA60tUgxYG+rJiyoW5hiJRpC8pNSSIqXtf5kvP5z HPB/eqfQa+yH1FgejL52ypUTf0jGLuWoa4M9sOmDhCiYjSjxTZo84dODDbBVefIGgo8eOTr /cap6RCNyokuoKSs8tC9YBUPHS+k05FzvJ9ag+n4eyx082OKboEmSFjEvO56V67AuPN4tRt wkgco8VyH/8N3XEyXnh7pVwpY+vNBkM1u/I/TYGj5RVATxtZZRLwNWk25anFlgjG8CFcxP3 zMIF8MYY93pNR5GQ2/iB+SDclBO/1DciPzLS32efSLIb8IRguT0H0R0b9DXyounZ2+qCOx4 z1Ck/+bJzEktryq74U8wrtIMgqPq1rWzduDyXcWBafHEPT1Mwhd6rbGgKhrtNifS9M7dXBm F2BVvCeraVi/oH4MWWptTqhLSo4UnYeq0h5LpYqN/lPqifW4/BpkWAWZPblfURwQL0z2SFZ ueMRuluV7L4m2x62xLudSf8p58qMx+Sve4774lf2+s9pXhPZa/gfKA/9FXmRX4+QJHPK+7+ xlk1U9/gd1ZpO5BkrveycDc/PL61qmQ1f3/PCq3TekzWtUJU7hjgYuY0zXrZh3xXO8gAZc4 SxvV7tyJdEb3GdBI59w2q74L8wFBCDq/wRHSt3pcEIzsVWs28Ir5mfivebln5J4OPSz95MJ wKtUIOTc8eOFUC+XOb6P2AHAi/5X7NQjEgJvPz/8jcZl0DkHGLIDGZhAe X-QQ-XMRINFO: OD9hHCdaPRBwq3WW+NvGbIU= X-QQ-RECHKSPAM: 0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Chaoyi Chen This patch add support for get PHY lane info without help of extcon. There is no extcon needed if the Type-C controller is present. In this case, the lane info can be get from PHY instead of extcon. The extcon device should still be supported if Type-C controller is not present. Signed-off-by: Chaoyi Chen --- Changes in v4: - Remove cdn_dp_hpd_notify(). (no changes since v3) Changes in v2: - Ignore duplicate HPD events. drivers/gpu/drm/rockchip/cdn-dp-core.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockc= hip/cdn-dp-core.c index b7e3f5dcf8d5..1e27301584a4 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -156,6 +156,9 @@ static int cdn_dp_get_port_lanes(struct cdn_dp_port *po= rt) int dptx; u8 lanes; =20 + if (!edev) + return phy_get_bus_width(port->phy); + dptx =3D extcon_get_state(edev, EXTCON_DISP_DP); if (dptx > 0) { extcon_get_property(edev, EXTCON_DISP_DP, @@ -219,7 +222,7 @@ static bool cdn_dp_check_sink_connection(struct cdn_dp_= device *dp) * some docks need more time to power up. */ while (time_before(jiffies, timeout)) { - if (!extcon_get_state(port->extcon, EXTCON_DISP_DP)) + if (port->extcon && !extcon_get_state(port->extcon, EXTCON_DISP_DP)) return false; =20 if (!cdn_dp_get_sink_count(dp, &sink_count)) @@ -385,11 +388,14 @@ static int cdn_dp_enable_phy(struct cdn_dp_device *dp= , struct cdn_dp_port *port) goto err_power_on; } =20 - ret =3D extcon_get_property(port->extcon, EXTCON_DISP_DP, - EXTCON_PROP_USB_TYPEC_POLARITY, &property); - if (ret) { - DRM_DEV_ERROR(dp->dev, "get property failed\n"); - goto err_power_on; + property.intval =3D 0; + if (port->extcon) { + ret =3D extcon_get_property(port->extcon, EXTCON_DISP_DP, + EXTCON_PROP_USB_TYPEC_POLARITY, &property); + if (ret) { + DRM_DEV_ERROR(dp->dev, "get property failed\n"); + goto err_power_on; + } } =20 port->lanes =3D cdn_dp_get_port_lanes(port); @@ -1028,6 +1034,9 @@ static int cdn_dp_bind(struct device *dev, struct dev= ice *master, void *data) for (i =3D 0; i < dp->ports; i++) { port =3D dp->port[i]; =20 + if (!port->extcon) + continue; + port->event_nb.notifier_call =3D cdn_dp_pd_event; ret =3D devm_extcon_register_notifier(dp->dev, port->extcon, EXTCON_DISP_DP, @@ -1120,14 +1129,14 @@ static int cdn_dp_probe(struct platform_device *pde= v) PTR_ERR(phy) =3D=3D -EPROBE_DEFER) return -EPROBE_DEFER; =20 - if (IS_ERR(extcon) || IS_ERR(phy)) + if (IS_ERR(phy) || PTR_ERR(extcon) !=3D -ENODEV) continue; =20 port =3D devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); if (!port) return -ENOMEM; =20 - port->extcon =3D extcon; + port->extcon =3D IS_ERR(extcon) ? NULL : extcon; port->phy =3D phy; port->dp =3D dp; port->id =3D i; --=20 2.49.0 From nobody Thu Oct 2 06:16:46 2025 Received: from smtpbguseast2.qq.com (smtpbguseast2.qq.com [54.204.34.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 44CE716FF37; Mon, 22 Sep 2025 01:21:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.204.34.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758504108; cv=none; b=JhZdKVtqX9M/0xWaLm4gIp0E3sti0lBpgX99vevTBorVtvRYWE1wap71gLXp5haJ1bqRE5JbsuVuU0ZfGrQ8e9Zjzmr9QEboHRbS6NHylO5xkwikQa3zXIGc3uikC5wfcMuhBW9ayjSG4oAWUgiRTDkrjIa4rmumAKWG48NIeNI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758504108; c=relaxed/simple; bh=2J7LCXGi7hmOODLgiUSwoCS9dK7aX0PuXTASbi58KUk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=sYynlsXEIqv2srUSe00k9K2O7e16K53i2FS6ywnEq2tozLnCs5ZolFwOAEGMR8tUQEKupy/Nd41EJU4VCdhSTmuA2Dp2yQqe4fdXL7q+waFQyIqCC0UYr4g7UFGdENihH3hb0t6edMJs1dXYXu4ItD8I/bQ9fry2kXOIU0gYs6k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=airkyi.com; spf=pass smtp.mailfrom=airkyi.com; dkim=pass (1024-bit key) header.d=airkyi.com header.i=@airkyi.com header.b=IAtuk+Fh; arc=none smtp.client-ip=54.204.34.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=airkyi.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=airkyi.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=airkyi.com header.i=@airkyi.com header.b="IAtuk+Fh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=airkyi.com; s=altu2504; t=1758504068; bh=luM6lBNu5ZO4eNeOMMICfFk3qQPUgvjzbZ7GZBNmaHc=; h=From:To:Subject:Date:Message-Id; b=IAtuk+FhLKxfis8lYqUtY7k6JNtgVfMoy6MGrLeARZwDBH7I9As38/hoTOcn+WAXe 8AavmMPKPEUJzP7X6OxEiebzqwhXIcaGE8CFXxzih5BED0zSmN/ZOmXOT6InGMeZoh dPjS9VktCske//fYGIxKbOSJ7ckTTEozk07uDP/E= X-QQ-mid: zesmtpgz1t1758504067t09a019ba X-QQ-Originating-IP: uWrsAC1547ktHVw/jlIhRv4jzPxTE/lpkp2cBqqMum8= Received: from DESKTOP-8BT1A2O.localdomain ( [58.22.7.114]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 22 Sep 2025 09:21:04 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 15475593906797426768 From: Chaoyi Chen To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Vinod Koul , Kishon Vijay Abraham I , Heiko Stuebner , Sandy Huang , Andy Yan , Yubing Zhang , Frank Wang , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Amit Sunil Dhamne , Heikki Krogerus , Greg Kroah-Hartman , Chaoyi Chen , Dragan Simic , Johan Jonker , Diederik de Haas , Dmitry Baryshkov , Peter Robinson Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, dri-devel@lists.freedesktop.org Subject: [PATCH v4 5/7] drm/rockchip: cdn-dp: Add multiple bridges to support PHY port selection Date: Mon, 22 Sep 2025 09:20:37 +0800 Message-Id: <20250922012039.323-6-kernel@airkyi.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20250922012039.323-1-kernel@airkyi.com> References: <20250922012039.323-1-kernel@airkyi.com> X-QQ-SENDSIZE: 520 Feedback-ID: zesmtpgz:airkyi.com:qybglogicsvrsz:qybglogicsvrsz4a-0 X-QQ-XMAILINFO: MyirvGjpKb1jFfeLshlYyh/zRpjC2fSJOSxa7UG8t7Ir4Dtm+qLL9Ihl RhQ6n8uSHV7Tg8PeIjkoTtnsudFCipgT8DWefwW4OiQIhg8O3z7gEH49qwp7m2+JVEsHqGP eje+02D5sSb0Uxpel4QPEi2Uxzuugk1NER0BiSQPiadAJm6oobVewHk5hmK72CW7dDm2Qgr yE+CQDS/W9p4qzA15nJO9XCh+NBZh8qN8t2INPoUdPsaUbLicj0Tat8uPYq1Tgg73jejess a5LonZz0Yayt8IXDkhFPrCXLxsmDWqBm+my152Qhl513WDuGA/HjuN7rYrKdqfopp/THzwS R23Hx7XVGdod9KSmPmpzzos1emgSXG5IBgJ+7bYA2HRlSa2s+EFIfhnGbfVaIkqnVuTFbN3 t3wiTX7SXe1CjHfzUOvbcw2KP15XJFST2v6N8ESjHXrsfXjk6otatai/7XN5/zjdvKPbD8y C1TjRho5yVW6utHyyTX0Q1kdMbRfX0ToNdVFaE+Eryf9w6FKnnUFR3aqka9836F4WqiLNQi 6PG+Dt5f6pxuFp00ip/8sMxdSQV/1ZwfYL8kuxu8l7IdjbP3qZW12hhVRRq5jkN4T/RyO3S K1bHLtVa2oCb/PuWPH67Q5si8H7WyAQIhQkvuOhvSgxD8qRHdBP7zabjr0IDY5bwiQIo913 dWPJXxxygEYGn+ChILT7Jrwssra/c3uM3mIFE/5szgkZHWWzUhf5FNB21dVj6mEkS6mJDT2 3wnq8q1KwWLrmJEUs1Wy5uJ0NVxngLQNbsuVmZ5tcvlCgsZ8P8EoBEkpA5ZK46ZaitM/LL1 A6WR8uzBSZcal0LEjh/J+h+14ByL7K5d9Gi36cOYH8fJyZ9zr22tfQEqcSVMuVbrk9vCxlp H5/UnEOTyAdJJEzYzMnetgtq0CgvkvDxhVT3eiWI/99yWFW+c48QEABjZ/8FOziqm7mVO2k 8XRSunsu2EsDRNjtvLafBtMfNPe8Q6PF0zhRM9rQ1OnAPMss7QJPggkS/YRkpuDYvNWW6Uw AZM9uOqg== X-QQ-XMRINFO: Nq+8W0+stu50PRdwbJxPCL0= X-QQ-RECHKSPAM: 0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Chaoyi Chen The RK3399 has two USB/DP combo PHY and one CDN-DP controller. And the CDN-DP can be switched to output to one of the PHYs. If both ports are plugged into DP, DP will select the first port for output. This patch adds support for multiple bridges, enabling users to flexibly select the output port. For each PHY port, a separate encoder and bridge are registered. The change is based on the DRM AUX HPD bridge, rather than the extcon approach. This requires the DT to correctly describe the connections between the PHY, USB connector, and DP controller. And cdn_dp_parse_hpd_bridge_dt() will parses it and determines whether to register one or two bridges. Since there is only one DP controller, only one of the PHY ports can output at a time. The key is how to switch between different PHYs, which is handled by cdn_dp_switch_port() and cdn_dp_enable(). There are two cases: 1. Neither bridge is enabled. In this case, both bridges can independently read the EDID, and the PHY port may switch before reading the EDID. 2. One bridge is already enabled. In this case, other bridges are not allowed to read the EDID. Since the scenario of two ports plug in at the same time is rare, I don't have a board which support two TypeC connector to test this. Therefore, I tested forced switching on a single PHY port, as well as output using a fake PHY port alongside a real PHY port. Signed-off-by: Chaoyi Chen --- drivers/gpu/drm/rockchip/Kconfig | 1 + drivers/gpu/drm/rockchip/cdn-dp-core.c | 398 +++++++++++++++++++++---- drivers/gpu/drm/rockchip/cdn-dp-core.h | 23 +- 3 files changed, 366 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kc= onfig index faf50d872be3..3a6266279323 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -55,6 +55,7 @@ config ROCKCHIP_CDN_DP select DRM_DISPLAY_HELPER select DRM_BRIDGE_CONNECTOR select DRM_DISPLAY_DP_HELPER + select DRM_AUX_HPD_BRIDGE help This selects support for Rockchip SoC specific extensions for the cdn DP driver. If you want to enable Dp on diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockc= hip/cdn-dp-core.c index 1e27301584a4..784f5656fcc4 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -27,16 +27,17 @@ #include "cdn-dp-core.h" #include "cdn-dp-reg.h" =20 -static inline struct cdn_dp_device *bridge_to_dp(struct drm_bridge *bridge) +static int cdn_dp_switch_port(struct cdn_dp_device *dp, struct cdn_dp_port= *prev_port, + struct cdn_dp_port *port); + +static inline struct cdn_dp_bridge *bridge_to_dp_bridge(struct drm_bridge = *bridge) { - return container_of(bridge, struct cdn_dp_device, bridge); + return container_of(bridge, struct cdn_dp_bridge, bridge); } =20 -static inline struct cdn_dp_device *encoder_to_dp(struct drm_encoder *enco= der) +static inline struct cdn_dp_device *bridge_to_dp(struct drm_bridge *bridge) { - struct rockchip_encoder *rkencoder =3D to_rockchip_encoder(encoder); - - return container_of(rkencoder, struct cdn_dp_device, encoder); + return bridge_to_dp_bridge(bridge)->parent; } =20 #define GRF_SOC_CON9 0x6224 @@ -191,14 +192,27 @@ static int cdn_dp_get_sink_count(struct cdn_dp_device= *dp, u8 *sink_count) static struct cdn_dp_port *cdn_dp_connected_port(struct cdn_dp_device *dp) { struct cdn_dp_port *port; - int i, lanes; + int i, lanes[MAX_PHY]; =20 for (i =3D 0; i < dp->ports; i++) { port =3D dp->port[i]; - lanes =3D cdn_dp_get_port_lanes(port); - if (lanes) + lanes[i] =3D cdn_dp_get_port_lanes(port); + if (!dp->hpd_bridge_valid) return port; } + + if (dp->hpd_bridge_valid) { + /* If more than one port is available, pick the last active port */ + if (dp->active_port > 0 && lanes[dp->active_port]) + return dp->port[dp->active_port]; + + /* If the last active port is not available, pick an available port in o= rder */ + for (i =3D 0; i < dp->bridge_count; i++) { + if (lanes[i]) + return dp->port[i]; + } + } + return NULL; } =20 @@ -239,10 +253,11 @@ static enum drm_connector_status cdn_dp_bridge_detect(struct drm_bridge *bridge, struct drm_connector *conn= ector) { struct cdn_dp_device *dp =3D bridge_to_dp(bridge); + struct cdn_dp_bridge *dp_bridge =3D bridge_to_dp_bridge(bridge); enum drm_connector_status status =3D connector_status_disconnected; =20 mutex_lock(&dp->lock); - if (dp->connected) + if (dp_bridge->connected && dp->connected) status =3D connector_status_connected; mutex_unlock(&dp->lock); =20 @@ -253,10 +268,36 @@ static const struct drm_edid * cdn_dp_bridge_edid_read(struct drm_bridge *bridge, struct drm_connector *c= onnector) { struct cdn_dp_device *dp =3D bridge_to_dp(bridge); - const struct drm_edid *drm_edid; + struct cdn_dp_bridge *dp_bridge =3D bridge_to_dp_bridge(bridge); + struct cdn_dp_port *port =3D dp->port[dp_bridge->id]; + struct cdn_dp_port *prev_port; + const struct drm_edid *drm_edid =3D NULL; + int i, ret; =20 mutex_lock(&dp->lock); + + /* More than one port is available */ + if (dp->bridge_count > 1 && !port->phy_enabled) { + for (i =3D 0; i < dp->bridge_count; i++) { + /* Another port already enable */ + if (dp->bridge_list[i] !=3D dp_bridge && dp->bridge_list[i]->enabled) + goto unlock; + /* Find already enabled port */ + if (dp->port[i]->phy_enabled) + prev_port =3D dp->port[i]; + } + + /* Switch to current port */ + if (prev_port) { + ret =3D cdn_dp_switch_port(dp, prev_port, port); + if (ret) + goto unlock; + } + } + drm_edid =3D drm_edid_read_custom(connector, cdn_dp_get_edid_block, dp); + +unlock: mutex_unlock(&dp->lock); =20 return drm_edid; @@ -267,12 +308,13 @@ cdn_dp_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *display_info, const struct drm_display_mode *mode) { + struct cdn_dp_bridge *dp_bridge =3D bridge_to_dp_bridge(bridge); struct cdn_dp_device *dp =3D bridge_to_dp(bridge); u32 requested, actual, rate, sink_max, source_max =3D 0; u8 lanes, bpc; =20 /* If DP is disconnected, every mode is invalid */ - if (!dp->connected) + if (!dp_bridge->connected || !dp->connected) return MODE_BAD; =20 switch (display_info->bpc) { @@ -571,6 +613,7 @@ static void cdn_dp_display_info_update(struct cdn_dp_de= vice *dp, static void cdn_dp_bridge_atomic_enable(struct drm_bridge *bridge, struct = drm_atomic_state *state) { struct cdn_dp_device *dp =3D bridge_to_dp(bridge); + struct cdn_dp_bridge *dp_bridge =3D bridge_to_dp_bridge(bridge); struct drm_connector *connector; int ret, val; =20 @@ -580,7 +623,7 @@ static void cdn_dp_bridge_atomic_enable(struct drm_brid= ge *bridge, struct drm_at =20 cdn_dp_display_info_update(dp, &connector->display_info); =20 - ret =3D drm_of_encoder_active_endpoint_id(dp->dev->of_node, &dp->encoder.= encoder); + ret =3D drm_of_encoder_active_endpoint_id(dp->dev->of_node, &dp_bridge->e= ncoder.encoder); if (ret < 0) { DRM_DEV_ERROR(dp->dev, "Could not get vop id, %d", ret); return; @@ -599,6 +642,9 @@ static void cdn_dp_bridge_atomic_enable(struct drm_brid= ge *bridge, struct drm_at =20 mutex_lock(&dp->lock); =20 + if (dp->hpd_bridge_valid) + dp->active_port =3D dp_bridge->id; + ret =3D cdn_dp_enable(dp); if (ret) { DRM_DEV_ERROR(dp->dev, "Failed to enable bridge %d\n", @@ -631,6 +677,7 @@ static void cdn_dp_bridge_atomic_enable(struct drm_brid= ge *bridge, struct drm_at goto out; } =20 + dp_bridge->enabled =3D true; out: mutex_unlock(&dp->lock); } @@ -638,9 +685,11 @@ static void cdn_dp_bridge_atomic_enable(struct drm_bri= dge *bridge, struct drm_at static void cdn_dp_bridge_atomic_disable(struct drm_bridge *bridge, struct= drm_atomic_state *state) { struct cdn_dp_device *dp =3D bridge_to_dp(bridge); + struct cdn_dp_bridge *dp_bridge =3D bridge_to_dp_bridge(bridge); int ret; =20 mutex_lock(&dp->lock); + dp_bridge->enabled =3D false; =20 if (dp->active) { ret =3D cdn_dp_disable(dp); @@ -885,7 +934,8 @@ static void cdn_dp_pd_event_work(struct work_struct *wo= rk) { struct cdn_dp_device *dp =3D container_of(work, struct cdn_dp_device, event_work); - int ret; + bool connected; + int i, ret; =20 mutex_lock(&dp->lock); =20 @@ -944,9 +994,12 @@ static void cdn_dp_pd_event_work(struct work_struct *w= ork) =20 out: mutex_unlock(&dp->lock); - drm_bridge_hpd_notify(&dp->bridge, - dp->connected ? connector_status_connected - : connector_status_disconnected); + for (i =3D 0; i < dp->bridge_count; i++) { + connected =3D dp->connected && dp->bridge_list[i]->connected; + drm_bridge_hpd_notify(&dp->bridge_list[i]->bridge, + connected ? connector_status_connected + : connector_status_disconnected); + } } =20 static int cdn_dp_pd_event(struct notifier_block *nb, @@ -966,28 +1019,99 @@ static int cdn_dp_pd_event(struct notifier_block *nb, return NOTIFY_DONE; } =20 -static int cdn_dp_bind(struct device *dev, struct device *master, void *da= ta) +static void cdn_dp_typec_hpd_cb(void *data, enum drm_connector_status stat= us) { - struct cdn_dp_device *dp =3D dev_get_drvdata(dev); - struct drm_encoder *encoder; - struct drm_connector *connector; - struct cdn_dp_port *port; - struct drm_device *drm_dev =3D data; - int ret, i; + struct cdn_dp_hpd_bridge *hpd_bridge =3D data; + struct cdn_dp_device *dp =3D hpd_bridge->parent; =20 - ret =3D cdn_dp_parse_dt(dp); - if (ret < 0) - return ret; + dp->bridge_list[hpd_bridge->id]->connected =3D status =3D=3D connector_st= atus_connected; + schedule_work(&dp->event_work); +} =20 - dp->drm_dev =3D drm_dev; - dp->connected =3D false; - dp->active =3D false; - dp->active_port =3D -1; - dp->fw_loaded =3D false; +static void cdn_dp_bridge_hpd_enable(struct cdn_dp_device *dp) +{ + int i; =20 - INIT_WORK(&dp->event_work, cdn_dp_pd_event_work); + if (!dp->hpd_bridge_valid) + return; + + for (i =3D 0; i < dp->bridge_count; i++) { + drm_bridge_hpd_enable(dp->hpd_bridge_list[i].bridge, cdn_dp_typec_hpd_cb, + &dp->hpd_bridge_list[i]); + } +} + +static void cdn_dp_bridge_hpd_disable(struct cdn_dp_device *dp) +{ + int i; + + if (!dp->hpd_bridge_valid) + return; + + for (i =3D 0; i < dp->bridge_count; i++) { + drm_bridge_hpd_disable(dp->hpd_bridge_list[i].bridge); + } +} + +static int cdn_dp_switch_port(struct cdn_dp_device *dp, struct cdn_dp_port= *prev_port, + struct cdn_dp_port *port) +{ + int ret; + + if (dp->active) + return 0; + + cdn_dp_bridge_hpd_disable(dp); + + ret =3D cdn_dp_disable_phy(dp, prev_port); + if (ret) + goto out; + ret =3D cdn_dp_enable_phy(dp, port); + if (ret) + goto out; + + ret =3D cdn_dp_get_sink_capability(dp); + if (ret) { + cdn_dp_disable_phy(dp, port); + goto out; + } + + dp->active =3D true; + dp->lanes =3D port->lanes; + + if (!cdn_dp_check_link_status(dp)) { + dev_info(dp->dev, "Connected with sink; re-train link\n"); + + ret =3D cdn_dp_train_link(dp); + if (ret) { + dev_err(dp->dev, "Training link failed: %d\n", ret); + goto out; + } + + ret =3D cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE); + if (ret) { + dev_err(dp->dev, "Failed to idle video %d\n", ret); + goto out; + } + + ret =3D cdn_dp_config_video(dp); + if (ret) + dev_err(dp->dev, "Failed to configure video: %d\n", ret); + } =20 - encoder =3D &dp->encoder.encoder; +out: + cdn_dp_bridge_hpd_enable(dp); + return ret; +} + +static int cdn_bridge_add(struct device *dev, + struct drm_bridge *bridge, + struct drm_encoder *encoder) +{ + struct cdn_dp_device *dp =3D dev_get_drvdata(dev); + struct drm_device *drm_dev =3D dp->drm_dev; + struct drm_connector *connector; + int ret; =20 encoder->possible_crtcs =3D drm_of_find_possible_crtcs(drm_dev, dev->of_node); @@ -1002,23 +1126,23 @@ static int cdn_dp_bind(struct device *dev, struct d= evice *master, void *data) =20 drm_encoder_helper_add(encoder, &cdn_dp_encoder_helper_funcs); =20 - dp->bridge.ops =3D - DRM_BRIDGE_OP_DETECT | - DRM_BRIDGE_OP_EDID | - DRM_BRIDGE_OP_HPD | - DRM_BRIDGE_OP_DP_AUDIO; - dp->bridge.of_node =3D dp->dev->of_node; - dp->bridge.type =3D DRM_MODE_CONNECTOR_DisplayPort; - dp->bridge.hdmi_audio_dev =3D dp->dev; - dp->bridge.hdmi_audio_max_i2s_playback_channels =3D 8; - dp->bridge.hdmi_audio_spdif_playback =3D 1; - dp->bridge.hdmi_audio_dai_port =3D -1; - - ret =3D devm_drm_bridge_add(dev, &dp->bridge); + bridge->ops =3D + DRM_BRIDGE_OP_DETECT | + DRM_BRIDGE_OP_EDID | + DRM_BRIDGE_OP_HPD | + DRM_BRIDGE_OP_DP_AUDIO; + bridge->of_node =3D dp->dev->of_node; + bridge->type =3D DRM_MODE_CONNECTOR_DisplayPort; + bridge->hdmi_audio_dev =3D dp->dev; + bridge->hdmi_audio_max_i2s_playback_channels =3D 8; + bridge->hdmi_audio_spdif_playback =3D 1; + bridge->hdmi_audio_dai_port =3D -1; + + ret =3D devm_drm_bridge_add(dev, bridge); if (ret) return ret; =20 - ret =3D drm_bridge_attach(encoder, &dp->bridge, NULL, DRM_BRIDGE_ATTACH_N= O_CONNECTOR); + ret =3D drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CON= NECTOR); if (ret) return ret; =20 @@ -1031,6 +1155,167 @@ static int cdn_dp_bind(struct device *dev, struct d= evice *master, void *data) =20 drm_connector_attach_encoder(connector, encoder); =20 + return 0; +} + +static int cdn_dp_parse_hpd_bridge_dt(struct cdn_dp_device *dp) +{ + struct device_node *np =3D dp->dev->of_node; + struct device_node *port __free(device_node) =3D of_graph_get_port_by_id(= np, 1); + struct drm_bridge *bridge; + int count =3D 0; + int ret =3D 0; + int i; + + /* If device use extcon, do not use hpd bridge */ + for (i =3D 0; i < dp->ports; i++) { + if (dp->port[i]->extcon) { + dp->bridge_count =3D 1; + return 0; + } + } + + /* + * + * &dp_out { + * dp_controller_output0: endpoint@0 { + * remote-endpoint =3D <&dp_phy0_in> + * }; + * + * dp_controller_output1: endpoint@1 { + * remote-endpoint =3D <&dp_phy1_in> + * }; + * }; + * + * &tcphy0_dp { + * port { + * tcphy0_typec_dp: endpoint@0 { + * reg =3D <0>; + * remote-endpoint =3D <&usbc0_dp>; + * }; + * + * dp_phy0_in: endpoint@1 { + * reg =3D <1>; + * remote-endpoint =3D <&dp_controller_output0>; + * }; + * }; + * }; + * + * &tcphy1_dp { + * ... + * }; + * + * usbcon0: connector { + * ... + * ports { + * ... + * port@2 { + * reg =3D <2>; + * + * usbc0_dp: endpoint { + * remote-endpoint =3D <&tcphy0_typec_dp>; + * }; + * }; + * }; + * }; + * + * usbcon1: connector { + * ... + * }; + * + */ + + /* One endpoint may correspond to one HPD bridge. */ + for_each_of_graph_port_endpoint(port, dp_ep) { + /* Try to get "port" node of correspond PHY device */ + struct device_node *phy_ep __free(device_node) =3D + of_graph_get_remote_endpoint(dp_ep); + struct device_node *phy_port __free(device_node) =3D + of_get_parent(phy_ep); + + if (!phy_port) { + continue; + } + + /* + * A PHY port may contain two endpoints: USB connector port or CDN-DP po= rt. + * Try to find the node of USB connector. + */ + for_each_of_graph_port_endpoint(phy_port, typec_ep) { + struct device_node *connector_port __free(device_node) =3D + of_graph_get_remote_port_parent(typec_ep); + struct device_node *hpd_bridge_np __free(device_node) =3D + of_get_parent(connector_port); + + if (typec_ep =3D=3D phy_ep) + continue; + + bridge =3D of_drm_find_bridge(hpd_bridge_np); + if (!bridge) { + ret =3D -EPROBE_DEFER; + goto out; + } + + dp->hpd_bridge_valid =3D true; + dp->hpd_bridge_list[count].bridge =3D bridge; + dp->hpd_bridge_list[count].parent =3D dp; + dp->hpd_bridge_list[count].id =3D count; + count++; + break; + } + } + +out: + dp->bridge_count =3D count ? count : 1; + return ret; +} + +static int cdn_dp_bind(struct device *dev, struct device *master, void *da= ta) +{ + struct cdn_dp_device *dp =3D dev_get_drvdata(dev); + struct drm_bridge *bridge; + struct drm_encoder *encoder; + struct cdn_dp_port *port; + struct drm_device *drm_dev =3D data; + struct cdn_dp_bridge *bridge_list; + int ret, i; + + ret =3D cdn_dp_parse_dt(dp); + if (ret < 0) + return ret; + + ret =3D cdn_dp_parse_hpd_bridge_dt(dp); + if (ret) + return ret; + + dp->drm_dev =3D drm_dev; + dp->connected =3D false; + dp->active =3D false; + dp->active_port =3D -1; + dp->fw_loaded =3D false; + + for (i =3D 0; i < dp->bridge_count; i++) { + bridge_list =3D devm_drm_bridge_alloc(dev, struct cdn_dp_bridge, bridge, + &cdn_dp_bridge_funcs); + if (IS_ERR(bridge_list)) + return PTR_ERR(bridge_list); + bridge_list->id =3D i; + bridge_list->parent =3D dp; + if (!dp->hpd_bridge_valid) + bridge_list->connected =3D true; + dp->bridge_list[i] =3D bridge_list; + } + + for (i =3D 0; i < dp->bridge_count; i++) { + encoder =3D &dp->bridge_list[i]->encoder.encoder; + bridge =3D &dp->bridge_list[i]->bridge; + ret =3D cdn_bridge_add(dev, bridge, encoder); + if (ret) + return ret; + } + + INIT_WORK(&dp->event_work, cdn_dp_pd_event_work); + for (i =3D 0; i < dp->ports; i++) { port =3D dp->port[i]; =20 @@ -1050,6 +1335,7 @@ static int cdn_dp_bind(struct device *dev, struct dev= ice *master, void *data) =20 pm_runtime_enable(dev); =20 + cdn_dp_bridge_hpd_enable(dp); schedule_work(&dp->event_work); =20 return 0; @@ -1058,10 +1344,14 @@ static int cdn_dp_bind(struct device *dev, struct d= evice *master, void *data) static void cdn_dp_unbind(struct device *dev, struct device *master, void = *data) { struct cdn_dp_device *dp =3D dev_get_drvdata(dev); - struct drm_encoder *encoder =3D &dp->encoder.encoder; + struct drm_encoder *encoder; + int i; =20 cancel_work_sync(&dp->event_work); - encoder->funcs->destroy(encoder); + for (i =3D 0; i < dp->bridge_count; i++) { + encoder =3D &dp->bridge_list[i]->encoder.encoder; + encoder->funcs->destroy(encoder); + } =20 pm_runtime_disable(dev); if (dp->fw_loaded) @@ -1112,10 +1402,10 @@ static int cdn_dp_probe(struct platform_device *pde= v) int ret; int i; =20 - dp =3D devm_drm_bridge_alloc(dev, struct cdn_dp_device, bridge, - &cdn_dp_bridge_funcs); - if (IS_ERR(dp)) - return PTR_ERR(dp); + dp =3D devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); + if (!dp) + return -ENOMEM; + dp->dev =3D dev; =20 match =3D of_match_node(cdn_dp_dt_ids, pdev->dev.of_node); diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockc= hip/cdn-dp-core.h index e9c30b9fd543..215f3da61af2 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.h +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h @@ -38,6 +38,8 @@ enum vic_pxl_encoding_format { Y_ONLY =3D 0x10, }; =20 +struct cdn_dp_device; + struct video_info { bool h_sync_polarity; bool v_sync_polarity; @@ -63,16 +65,33 @@ struct cdn_dp_port { u8 id; }; =20 +struct cdn_dp_bridge { + struct cdn_dp_device *parent; + struct drm_bridge bridge; + struct rockchip_encoder encoder; + bool connected; + bool enabled; + int id; +}; + +struct cdn_dp_hpd_bridge { + struct cdn_dp_device *parent; + struct drm_bridge *bridge; + int id; +}; + struct cdn_dp_device { struct device *dev; struct drm_device *drm_dev; - struct drm_bridge bridge; - struct rockchip_encoder encoder; + int bridge_count; + struct cdn_dp_bridge *bridge_list[MAX_PHY]; + struct cdn_dp_hpd_bridge hpd_bridge_list[MAX_PHY]; struct drm_display_mode mode; struct platform_device *audio_pdev; struct work_struct event_work; =20 struct mutex lock; + bool hpd_bridge_valid; bool connected; bool active; bool suspended; --=20 2.49.0 From nobody Thu Oct 2 06:16:46 2025 Received: from smtpbgeu2.qq.com (smtpbgeu2.qq.com [18.194.254.142]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9990618DB35; Mon, 22 Sep 2025 01:21:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=18.194.254.142 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758504098; cv=none; b=aJx4gtjHqjfA47mJRRJ5Hg21ruDRLff2RoqvpGQBLRXv4fB80J10LrQQqzmmmtYh0xVSlk2IWZqOb1Ym6qa3jcF0x2gBRC6UZZTuAKV0I0OyE92PBPnqI1HTceZbCLi8c6TILb2GrjrdQFgVdhCu8Xhn5zsSmD0t9Gw8h9N4Alc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758504098; c=relaxed/simple; bh=jKgMxEif1Rvy22x6B1k063dU/ySK1MoA1J6lxiTaUmY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=T3+tleyipj8DzLL7LVrsZ/SEKlNM+JMdP/PCU7xRi+gItXV0CmeOFBsTIb1lXMtyRlcUUuRWk02mDNp9+d0Zs6sLZuAsPHAxpjlbaMxcAjffYFpjsy8HhNDm9+QUR4eufKbs8NWfbkaQlG8Cjr2g9PUml0rI09eAL8dvIHPaEew= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=airkyi.com; spf=pass smtp.mailfrom=airkyi.com; dkim=pass (1024-bit key) header.d=airkyi.com header.i=@airkyi.com header.b=u0yxSLlS; arc=none smtp.client-ip=18.194.254.142 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=airkyi.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=airkyi.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=airkyi.com header.i=@airkyi.com header.b="u0yxSLlS" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=airkyi.com; s=altu2504; t=1758504072; bh=FQiFCRapN/3mwb02ZP+dTFVgTrcEVb7y08IjRSvyuIY=; h=From:To:Subject:Date:Message-Id; b=u0yxSLlSwOATLLm30XMbWjPLBFDpyvoP2neidc+XQMfGEYWq3H5x1vzW5cWOAhydC Nn9CL4SK5uOmvEoLdZ8Vh9+U5MnkyToL6w/ufUa+aU32ptKsuIwg6fpf0dtreQteFF A/Dw9SfKJaM2iYtBkkivy6Yw4G5K5xxO+QXNkjCI= X-QQ-mid: zesmtpgz1t1758504070tb08ab248 X-QQ-Originating-IP: irFhF1T+2Su/4ccgz1o9QWkx8RvanKgMn5pFCBUgAAg= Received: from DESKTOP-8BT1A2O.localdomain ( [58.22.7.114]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 22 Sep 2025 09:21:08 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 16934661695937755636 From: Chaoyi Chen To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Vinod Koul , Kishon Vijay Abraham I , Heiko Stuebner , Sandy Huang , Andy Yan , Yubing Zhang , Frank Wang , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Amit Sunil Dhamne , Heikki Krogerus , Greg Kroah-Hartman , Chaoyi Chen , Dragan Simic , Johan Jonker , Diederik de Haas , Dmitry Baryshkov , Peter Robinson Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, dri-devel@lists.freedesktop.org Subject: [PATCH v4 6/7] arm64: dts: rockchip: Add missing dp_out port for RK3399 CDN-DP Date: Mon, 22 Sep 2025 09:20:38 +0800 Message-Id: <20250922012039.323-7-kernel@airkyi.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20250922012039.323-1-kernel@airkyi.com> References: <20250922012039.323-1-kernel@airkyi.com> X-QQ-SENDSIZE: 520 Feedback-ID: zesmtpgz:airkyi.com:qybglogicsvrsz:qybglogicsvrsz4a-0 X-QQ-XMAILINFO: NyTsQ4JOu2J27F0cQTRa45HVw4w+kK5tj4V0OnKDXBe5mvppmncfP6qp 45qLPwsmsJlTLz4jnSTS/RmllHiiinuwjHdH+oQf67NEm/tWkBZaIv7i5Uk4bYd6ID5Y8Hf mbApHF0PaxKxlSsJsMX28cm14O55JBFyyx1zvR+CLG+k6mS84cZsnNjxrcyc1RVgEzXVmR4 EIWvP1Pn4ncxHDbXb+2ysJmG91JEJZap8djcdA4zy5FqQCguX4XC2a1fgYg9o+z85vbabqk d9URqDtt4Y0ZAuAPiHk5uIhg7DaLkzT1zHO5CrqOZEvwbrBVg1eT0dY5jTr4qwrTx4YxEQ+ Ggo1zNrJxcP0iJjNe3B1XmnMKVdu/3tl5x+99TUlneD6rXKHuCyGLbADpYX7alzTWmKRb+I zfKUmztv2zdXbonRR8cHcm54C5/jUeLXkUEwlxNFNGT+23w8NXD3/0WNhK90YQaA9DNYDFY WHKfFBAVULS5uRQLDjegE0K0J0K7Md7VMjBrLxBXNw/Pv7NC1byeuyoxAajailPMSA6rugN dWUeRcP81GQlyDD2mDnxL3n7TfF+71EbZcPCTcNTVOiJqkRknPoIOW40e1+/TZkkz+q9dDJ hD0FUq7Ztfy1psggi98LzfXqrS3gQw+KygR1TdUgdLWYhQhVBNg71DFG6OMkVjxFO1D9Ozl uPF/r7r6H5bSfSn9IBLhyLcH/ShOYD3h1rixqXQzRyNObU5JRULJxabR5U5+viMhi4H+qkJ CGkemdZ72dadThq4dTFqD/q73mvYehM4bpiSvD3FrAO7hOfRlKSkm3gsrVA7gJ/h/3zpW/Q Zb482AzvsNXiWccewpPXb5ggZ7IO3U/hVbyByvLLMQpKo/I/y1cICWRg8djsfv9CmnD9szQ 02l9T0gz0h1WFPXEcTIKqJ1nKxJ4dbBSk/dA5z/R0iIBHwvue15BklpLU3T3CX8cKcVmUMh q/LYZQvSVw2kjEAMxUd3v/UBU41J4WUgUmR8MUThM7sythR/ZRn9S5EavMRzyXR2++dgdEN NC85ZIbPE4dJ4lDJI/ X-QQ-XMRINFO: MSVp+SPm3vtS1Vd6Y4Mggwc= X-QQ-RECHKSPAM: 0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Chaoyi Chen Let's make the ports nodes of cdn_dp in the same style as the other display interface, and match the style of ports's yaml. Signed-off-by: Chaoyi Chen --- Changes in v4: - Remove unnecessary #address/#size-cells (no changes since v1) arch/arm64/boot/dts/rockchip/rk3399-base.dtsi | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi b/arch/arm64/boo= t/dts/rockchip/rk3399-base.dtsi index 4dcceb9136b7..93b42820998f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi @@ -618,7 +618,11 @@ cdn_dp: dp@fec00000 { status =3D "disabled"; =20 ports { - dp_in: port { + #address-cells =3D <1>; + #size-cells =3D <0>; + + dp_in: port@0 { + reg =3D <0>; #address-cells =3D <1>; #size-cells =3D <0>; =20 @@ -632,6 +636,10 @@ dp_in_vopl: endpoint@1 { remote-endpoint =3D <&vopl_out_dp>; }; }; + + dp_out: port@1 { + reg =3D <1>; + }; }; }; =20 --=20 2.49.0 From nobody Thu Oct 2 06:16:46 2025 Received: from smtpbg154.qq.com (smtpbg154.qq.com [15.184.224.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3431A1F0E26; Mon, 22 Sep 2025 01:21:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=15.184.224.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758504108; cv=none; b=BsE/ltz7Nj4aPi9yKVb4w4XiG3IzKCpQZilOYnN8b6tA1/omkf/j/7lryhhJOnO4fPoV22G8OG2QtnJ3t86mGOk64Uowo9y8GEd2HgSVcWTHmJmiKIqrsATBNf0ZG8HPybaMS0xTiBDALFJAUQev2gID2eybLWO2ElcY9FETHTs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758504108; c=relaxed/simple; bh=Ksu1m13XDgyOSNrC/yix/S/ref0aCyYvyb9gG5K8i98=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=HDbJ9yfdoFI/eJWhXviSVswhCLRIbNFu/OIvMb1I5guqfLG2y9tuGS/T4A0UIcSg8XYJO2U54m1l33TCqlLhBxHwuOnYW78lRwLEwyGYXHNh7YzLnfXt7bO5PqOVypmCut6fAPenFe6X1x9PoPGQkXa97R8h27Idg0X3BkCFFk8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=airkyi.com; spf=pass smtp.mailfrom=airkyi.com; dkim=pass (1024-bit key) header.d=airkyi.com header.i=@airkyi.com header.b=YIA+WpA4; arc=none smtp.client-ip=15.184.224.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=airkyi.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=airkyi.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=airkyi.com header.i=@airkyi.com header.b="YIA+WpA4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=airkyi.com; s=altu2504; t=1758504076; bh=1RfAR5qe3fDpGYWfe4IMPee9wlWopj1wjBrVtJQSHJQ=; h=From:To:Subject:Date:Message-Id; b=YIA+WpA4o3OEuzDPcWy9lg1EOKRQQy00KTu/v9+wiyTTJJr1VjIyDVQ8YY70f80J3 tsN7t1kSOOY247lFd3vF3aVNTIJrYDrphr9F0ATUZHvmZK/aa07dSnNxWPjKs5FKsQ 3yLZ17chhgIC10vkUpStLzgf0V+UpqTK1kFR2CME= X-QQ-mid: zesmtpgz1t1758504074t6dfce6ba X-QQ-Originating-IP: lSGoq+HWt+ppL1YEpRWcbFVvWha0FUtEMUj0XnYRSgU= Received: from DESKTOP-8BT1A2O.localdomain ( [58.22.7.114]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 22 Sep 2025 09:21:12 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 16320942672691209888 From: Chaoyi Chen To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Vinod Koul , Kishon Vijay Abraham I , Heiko Stuebner , Sandy Huang , Andy Yan , Yubing Zhang , Frank Wang , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Amit Sunil Dhamne , Heikki Krogerus , Greg Kroah-Hartman , Chaoyi Chen , Dragan Simic , Johan Jonker , Diederik de Haas , Dmitry Baryshkov , Peter Robinson Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, dri-devel@lists.freedesktop.org Subject: [PATCH v4 7/7] arm64: dts: rockchip: rk3399-evb-ind: Add support for DisplayPort Date: Mon, 22 Sep 2025 09:20:39 +0800 Message-Id: <20250922012039.323-8-kernel@airkyi.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20250922012039.323-1-kernel@airkyi.com> References: <20250922012039.323-1-kernel@airkyi.com> X-QQ-SENDSIZE: 520 Feedback-ID: zesmtpgz:airkyi.com:qybglogicsvrsz:qybglogicsvrsz4a-0 X-QQ-XMAILINFO: MnSWAsm/ITbmaBYY/WP/ghYb+Yt3znOG9lmzjHjUBvPlyU9Z3DpfwwZo 1tibLDKDX0fd4nJTWWQgUs9IHlKBSjZU29w9HcIvhAyYlzfyVHDp2ur1W6jDgjG7cO3scXm MDuPDh2vl0b/xEinU4C+2zPXTV+nPDbPnDp1hkC52vllrcW591fgSNeXt0Qksz4wG5rRb/9 Fb4UnminWftWkdQtyLxzJ/AMyUASYR7xmZ7xct7vJn2KnJ613gP0qtnMoaqq7akPYLodqwP wQN79gTLG6uPnbit63oIA4f4jhYoQMKG/j5X3IguNfze6yLnBE58U+GZSY/EaGrwEMCAAA/ EbjLaNplthh7ZGSPFuYVLUJ/6c5E0B0F1Udpyiir//1SpsHp3o6OIhpoDjr4joFLZVpoil7 /yktmlxSLkrH6CHKdB3N911ewW+g4xKTYUb3FYAFt5jtdlBbsIVJlAVkK4ndOr+/n9LUdlI ax1vsLeOaBoSGJBAzpNN2Q8p0okfUHCd3sOzyc5FVGxalc9e/rgPUBTq6Lm3ZCXetUNvvg1 iFcuym4MigK7Lv8AY06DxyZLtLA/Yj9vZvo39IyFF13DQuNCW1du1P1w1wU8G8ZVxJYd1iS imEN7yV09nTwSEKkBl+DrG+wMgGshJfAnD3Qx8GpDO6BjqlGqXn9G57EHl0IEr2RA9tL5dk Pp85qk7ChXBUeaqax0JdZNYFC2y7bRx++c9190mrfdZXM8RMRFj2WOB4or07HGF6hKQKLSa FdmtIF7PcKsdabIw2TIKxxRi9kIs8FUfoFYtxG6kUnYxqK32f/i93uJuJ/OW2wCdM9dYV4Y oKAboz6DHMr4gO+YZtHzHBRs8XeLBPN1IVpdY7uORTBHkoM25+Ze6YayfbPjn/y1xnuGvz4 SUyAIqs2VEEJCgBr68jl6Ntg35fvHWuNUBtskhcIthn4jnabZbLpGp+Uev2fWeOW1XMBqiX ZpjbyN80dJQztewqr6dgx3XtZ/Cm/LcddEjP126FgvA8y9DXNkT6rlrEXa0NmTGz0Rqx9FH AzAwymsxRFPcI03S+wMaSp3ghQyic= X-QQ-XMRINFO: OD9hHCdaPRBwq3WW+NvGbIU= X-QQ-RECHKSPAM: 0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Chaoyi Chen The RK3399 EVB IND board has a Type-C interface DisplayPort. It use fusb302 chip as Type-C controller. fusb302 chip ---> USB/DP PHY0 <----> CDN-DP controller Signed-off-by: Chaoyi Chen --- (no changes since v4) Changes in v3: - Fix wrong vdo value. - Fix port node in usb-c-connector. Changes in v2: - Add endpoint to link DP PHY and DP controller. - Fix devicetree coding style. .../boot/dts/rockchip/rk3399-evb-ind.dts | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb-ind.dts b/arch/arm64/b= oot/dts/rockchip/rk3399-evb-ind.dts index 70aee1ab904c..aeeee6bd2973 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-evb-ind.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-evb-ind.dts @@ -4,6 +4,7 @@ */ =20 /dts-v1/; +#include #include "rk3399.dtsi" =20 / { @@ -19,6 +20,21 @@ chosen { stdout-path =3D "serial2:1500000n8"; }; =20 + sound: sound { + compatible =3D "rockchip,rk3399-gru-sound"; + rockchip,cpu =3D <&i2s0 &spdif>; + }; + + vbus_typec: regulator-vbus-typec { + compatible =3D "regulator-fixed"; + enable-active-high; + gpio =3D <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>; + pinctrl-names =3D "default"; + pinctrl-0 =3D <&vcc5v0_typec0_en>; + regulator-name =3D "vbus_typec"; + vin-supply =3D <&vcc5v0_sys>; + }; + vcc5v0_sys: regulator-vcc5v0-sys { compatible =3D "regulator-fixed"; enable-active-high; @@ -31,6 +47,11 @@ vcc5v0_sys: regulator-vcc5v0-sys { }; }; =20 +&cdn_dp { + phys =3D <&tcphy0_dp>; + status =3D "okay"; +}; + &cpu_b0 { cpu-supply =3D <&vdd_cpu_b>; }; @@ -55,6 +76,12 @@ &cpu_l3 { cpu-supply =3D <&vdd_cpu_l>; }; =20 +&dp_out { + dp_controller_output: endpoint { + remote-endpoint =3D <&dp_phy_in>; + }; +}; + &emmc_phy { status =3D "okay"; }; @@ -341,6 +368,71 @@ regulator-state-mem { }; }; =20 +&i2c4 { + i2c-scl-rising-time-ns =3D <475>; + i2c-scl-falling-time-ns =3D <26>; + status =3D "okay"; + + usbc0: typec-portc@22 { + compatible =3D "fcs,fusb302"; + reg =3D <0x22>; + interrupt-parent =3D <&gpio1>; + interrupts =3D ; + pinctrl-names =3D "default"; + pinctrl-0 =3D <&usbc0_int>; + vbus-supply =3D <&vbus_typec>; + + usb_con: connector { + compatible =3D "usb-c-connector"; + label =3D "USB-C"; + data-role =3D "dual"; + power-role =3D "dual"; + try-power-role =3D "sink"; + op-sink-microwatt =3D <1000000>; + sink-pdos =3D + ; + source-pdos =3D + ; + + altmodes { + displayport { + svid =3D /bits/ 16 <0xff01>; + vdo =3D <0x00001c46>; + }; + }; + + ports { + #address-cells =3D <1>; + #size-cells =3D <0>; + + port@0 { + reg =3D <0>; + + usbc_hs: endpoint { + remote-endpoint =3D <&u2phy0_typec_hs>; + }; + }; + + port@1 { + reg =3D <1>; + + usbc_ss: endpoint { + remote-endpoint =3D <&tcphy0_typec_ss>; + }; + }; + + port@2 { + reg =3D <2>; + + usbc_dp: endpoint { + remote-endpoint =3D <&tcphy0_typec_dp>; + }; + }; + }; + }; + }; +}; + &i2s2 { status =3D "okay"; }; @@ -354,6 +446,16 @@ &io_domains { }; =20 &pinctrl { + usb-typec { + usbc0_int: usbc0-int { + rockchip,pins =3D <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + vcc5v0_typec0_en: vcc5v0-typec0-en { + rockchip,pins =3D <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + pmic { pmic_int_l: pmic-int-l { rockchip,pins =3D <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; @@ -400,10 +502,48 @@ &sdmmc { status =3D "okay"; }; =20 +&sound { + rockchip,codec =3D <&cdn_dp>; + status =3D "okay"; +}; + +&spdif { + status =3D "okay"; +}; + &tcphy0 { status =3D "okay"; }; =20 +&tcphy0_dp { + mode-switch; + + port { + #address-cells =3D <1>; + #size-cells =3D <0>; + + tcphy0_typec_dp: endpoint@0 { + reg =3D <0>; + remote-endpoint =3D <&usbc_dp>; + }; + + dp_phy_in: endpoint@1 { + reg =3D <1>; + remote-endpoint =3D <&dp_controller_output>; + }; + }; +}; + +&tcphy0_usb3 { + orientation-switch; + + port { + tcphy0_typec_ss: endpoint { + remote-endpoint =3D <&usbc_ss>; + }; + }; +}; + &tcphy1 { status =3D "okay"; }; @@ -418,6 +558,12 @@ &tsadc { =20 &u2phy0 { status =3D "okay"; + + port { + u2phy0_typec_hs: endpoint { + remote-endpoint =3D <&usbc_hs>; + }; + }; }; =20 &u2phy0_host { --=20 2.49.0