From patchwork Fri Nov 29 07:57:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiangxu Yin X-Patchwork-Id: 13888464 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 05AACD6EBE6 for ; Fri, 29 Nov 2024 07:58:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:CC:To:In-Reply-To:References:Message-ID :MIME-Version:Subject:Date:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=aPb4eGGaaUwZbqz0hOo/qFdZaqrj5qjX6KyRlZ0lo2g=; b=zClYYlSAYPf8YA KSJrUg1E4oYPV7XWI8C0Xs5JyrHT9U+sa+cEPy5MMpN2cGSq66OfvVHn3GvavMwlxnRwrLTbB3SOc 8VV5bcEMLdavgD14NBQmNbkTCnfIGnxt2he1R7ggmbsmhFzeJ0N1TI+cPenizJRvk6+KkZXFoBgUe QB7AlwxS37gZK8FF+N5MFWC/uBOYEmhadmfLEuqjlVlcGNGQWUiKOEFQ6nkFvqJYRGqGecVRDA7mO 5SYhooFzgKZe1eD8r3ERLx33XSgCp7xjGTnDlURvhyzoKfCtC4W/XMzxx4hnOua7PFublnxZpRM2D VABcT6+JWUt0/JbWUueA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tGvts-0000000H7BS-0kg1; Fri, 29 Nov 2024 07:58:52 +0000 Received: from mx0a-0031df01.pphosted.com ([205.220.168.131]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tGvtp-0000000H7AW-21fu for linux-phy@lists.infradead.org; Fri, 29 Nov 2024 07:58:50 +0000 Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4ASMfxqI014340; Fri, 29 Nov 2024 07:58:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= NS32UssW8dHqvhKdozniXo0XF8+DxtclGm3SwL51JBw=; b=dl0mMZ0jkdHd3lVP sb3OL8Xf3u709NIWOY2bF8opeZ683W5XNq/pGHcyRLVlnBGMBPHD4mZAt/yuc5Cu tYqzD+T0wddujDrlId4dkXHzXGo5YynPw5iKlQNk9PPUPchx5EFnAfwuFfm7Dfbd C55gBkvNvCsMPt0ntHsqz6lwBWyghe4mTLqi2bCv76HydZDDgWf97c9xNsfZPLbq Cpuk5t3r96gG3cOxZNw91kjdiDV71brfw1xbDIG4DAGgpBup2Xp28aG4SobNws12 DL3MOfRqeUEAeApmo9EBKkGdVa3yBjDS+KrzdHzZjRX/h/kCxZkgGUlAZmsUgWzl V+I9Sw== Received: from nasanppmta05.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 43671ecrd3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:58:42 +0000 (GMT) Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA05.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AT7wfX5025117 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:58:41 GMT Received: from szioemm-lnxbld002.qualcomm.com (10.80.80.8) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 28 Nov 2024 23:58:33 -0800 From: Xiangxu Yin Date: Fri, 29 Nov 2024 15:57:41 +0800 Subject: [PATCH 1/8] dt-bindings: display/msm: Document DP on QCS615 MIME-Version: 1.0 Message-ID: <20241129-add-displayport-support-for-qcs615-platform-v1-1-09a4338d93ef@quicinc.com> References: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> In-Reply-To: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> To: Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Kuogee Hsieh , Vinod Koul , Kishon Vijay Abraham I , Linus Walleij , Bartosz Golaszewski , , CC: , , , , , , , Xiangxu Yin X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732867102; l=1433; i=quic_xiangxuy@quicinc.com; s=20241125; h=from:subject:message-id; bh=+Yc4b2vwMOMUcnhy+3PRkpU/S2QPiJtYGy+jm215PqY=; b=SM+aQp2qsJdegx3yOSGJbLaMppSV1CHq3Mi6hRrWpub+a6ouc+09NZqcx4CpfJn1uao4Qoo9P lqWZec09FRYAB/xemJprnGnysaxVHco7f4/5gRUZsEGQG/MKzZMWNbX X-Developer-Key: i=quic_xiangxuy@quicinc.com; a=ed25519; pk=F1TwipJzpywfbt3n/RPi4l/A4AVF+QC89XzCHgZYaOc= X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: eAIGp_6-P54BTI5KJ0I3w3Ct6dalNf2y X-Proofpoint-GUID: eAIGp_6-P54BTI5KJ0I3w3Ct6dalNf2y X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 suspectscore=0 impostorscore=0 mlxscore=0 phishscore=0 priorityscore=1501 clxscore=1015 bulkscore=0 lowpriorityscore=0 spamscore=0 adultscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2411290064 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241128_235849_552630_CF568EB3 X-CRM114-Status: GOOD ( 10.35 ) X-BeenThere: linux-phy@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux Phy Mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-phy" Errors-To: linux-phy-bounces+linux-phy=archiver.kernel.org@lists.infradead.org Document the DP hardware found on the Qualcomm QCS615 platform. Signed-off-by: Xiangxu Yin --- .../devicetree/bindings/display/msm/dp-controller.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index a212f335d5ffae545d2e5bacec95299ca45e8405..a609245ae601bdc60b65f19d3e59c559886a969d 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -26,6 +26,7 @@ properties: - qcom,sc8280xp-dp - qcom,sc8280xp-edp - qcom,sdm845-dp + - qcom,sm6150-dp - qcom,sm8350-dp - qcom,sm8650-dp - items: @@ -109,6 +110,18 @@ properties: vdda-1p2-supply: deprecated: true + max-width: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Maximum allowed width for display modes + default: 7680 + + dp-hpd-gpio: + description: External GPIO for controlling HPD when a 3rd pinctrl is used + items: + - description: phandle to 3rd GPIO controller + - description: GPIO pin number + - description: Optional GPIO flags + ports: $ref: /schemas/graph.yaml#/properties/ports properties: From patchwork Fri Nov 29 07:57:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiangxu Yin X-Patchwork-Id: 13888465 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id F2E51D6EBE2 for ; Fri, 29 Nov 2024 07:59:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:CC:To:In-Reply-To:References:Message-ID :MIME-Version:Subject:Date:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=xGluQTdy0ebriTyyxhl6MxZ4SPd2X9Lnjcvgd8mc0SM=; b=iPlXg4tR3WE78i P9hUl00mC7YtmrmuWbYXa7T4sKJOellewStiQHmn1Kaj5Id/foyXF+8hUPQBLZ2pDrk2kHJop6trJ Gy2HCcIwldGv4UUfSZPTDzHruEa8jzaenAv3hltnTsR62Rn3CXOWFJk0WU1BQHRppBZ31RYbMADM8 ZALUWjwhVEQszYYQggwykLbploxQaY6MhGLgQ8FYBPvbs7fn3KD7F7QDvtafmRkjZISaEFS10r8ht Sao0gY1Ft68RMyVoMRqfbtBXpROlcbLsGuOLEzYMxGj1GNuJ4osolbFKVUUymUZO0Ej58R+CxXDot us9b6h0pGowQg2zrDDhA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tGvu0-0000000H7F2-32Hz; Fri, 29 Nov 2024 07:59:00 +0000 Received: from mx0a-0031df01.pphosted.com ([205.220.168.131]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tGvtx-0000000H7DX-2k3J for linux-phy@lists.infradead.org; Fri, 29 Nov 2024 07:58:58 +0000 Received: from pps.filterd (m0279867.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4ASLbHKQ020107; Fri, 29 Nov 2024 07:58:50 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= iHDcSrf7IMXqPzRGIJNsXzGNg3ufK7n3UP/3AjN8dz8=; b=TKPgJwTfP0Mf0vW0 BKZtquyOyqvT6/Vfqex3GfVN7b7FCLj9KFeBvBrykegvVLGJli+CtFpYUwV8x6ck rGv+N3V6j03/k+u22Fma6MG00JLqAOvoVTDK4MUmZS+ma8FM4uRtQ6If1gdXXjbX BNyJLgXz7jNCi9WmzVz/Ti6JdxoDscBEyemrM/YJrkug0aJ3n8k+VSIW9eI3fE2S MsryAINVmgjPxaPygtvFnib13hBJYxyERHX9hEu1uN9erdUDxBJli59VgsCfIOn4 BQf8SzR0Zpb2psVk8Bezr7ZZKNNtHb9Pp8uLQa8Bg+rdIvv5I5VLLvAUUjBXWeQr e++Ddg== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4366xw4ugt-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:58:50 +0000 (GMT) Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AT7wnkW001991 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:58:49 GMT Received: from szioemm-lnxbld002.qualcomm.com (10.80.80.8) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 28 Nov 2024 23:58:41 -0800 From: Xiangxu Yin Date: Fri, 29 Nov 2024 15:57:42 +0800 Subject: [PATCH 2/8] dt-bindings: phy: qcom,msm8998-qmp-usb3-phy: Add DP support for QCS615 MIME-Version: 1.0 Message-ID: <20241129-add-displayport-support-for-qcs615-platform-v1-2-09a4338d93ef@quicinc.com> References: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> In-Reply-To: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> To: Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Kuogee Hsieh , Vinod Koul , Kishon Vijay Abraham I , Linus Walleij , Bartosz Golaszewski , , CC: , , , , , , , Xiangxu Yin X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732867103; l=1923; i=quic_xiangxuy@quicinc.com; s=20241125; h=from:subject:message-id; bh=26v/MR4YbXXYBMcul2oh+5YPYvjVNeh1jkpnZvHpQKQ=; b=z0z7ZC7r0DaeTTqW9anfyuAEXClEattvH1nZdxTSeGn7Y+lu8EuWC1u7xS+Oh99ZnU+8wzxgI /khh/IoPWkmDeYe3RfdrJBnpsLB6MntI0NI/NOZ4yzcWR/BTwQwrfNi X-Developer-Key: i=quic_xiangxuy@quicinc.com; a=ed25519; pk=F1TwipJzpywfbt3n/RPi4l/A4AVF+QC89XzCHgZYaOc= X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: -7dMOkuuHx3f_bJY3OAOfozjcJ8jhffl X-Proofpoint-ORIG-GUID: -7dMOkuuHx3f_bJY3OAOfozjcJ8jhffl X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 malwarescore=0 bulkscore=0 impostorscore=0 priorityscore=1501 clxscore=1011 mlxlogscore=999 phishscore=0 adultscore=0 spamscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2411290064 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241128_235857_699761_151AAD34 X-CRM114-Status: GOOD ( 11.51 ) X-BeenThere: linux-phy@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux Phy Mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-phy" Errors-To: linux-phy-bounces+linux-phy=archiver.kernel.org@lists.infradead.org Declare the DP QMP PHY present on the Qualcomm QCS615 platforms. Signed-off-by: Xiangxu Yin --- .../bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml index 1636285fbe535c430fdf792b33a5e9c523de323b..eb21cfe734526fce670c540212a607a016cedf2c 100644 --- a/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml @@ -18,6 +18,7 @@ properties: enum: - qcom,msm8998-qmp-usb3-phy - qcom,qcm2290-qmp-usb3-phy + - qcom,qcs615-qmp-dp-phy - qcom,qcs615-qmp-usb3-phy - qcom,sdm660-qmp-usb3-phy - qcom,sm6115-qmp-usb3-phy @@ -47,7 +48,7 @@ properties: const: 0 clock-output-names: - maxItems: 1 + maxItems: 2 "#phy-cells": const: 0 @@ -62,7 +63,8 @@ properties: items: - items: - description: phandle to TCSR hardware block - - description: offset of the VLS CLAMP register + - description: offset of the VLS CLAMP register in USB mode + and offset of the DP Phy mode register in DP mode description: Clamp register present in the TCSR ports: @@ -128,6 +130,21 @@ allOf: - const: com_aux - const: pipe + - if: + properties: + compatible: + contains: + enum: + - qcom,qcs615-qmp-dp-phy + then: + properties: + clocks: + maxItems: 2 + clock-names: + items: + - const: cfg_ahb + - const: ref + additionalProperties: false examples: From patchwork Fri Nov 29 07:57:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Xiangxu Yin X-Patchwork-Id: 13888467 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A6725D6EBE2 for ; Fri, 29 Nov 2024 07:59:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:CC:To:In-Reply-To:References:Message-ID :MIME-Version:Subject:Date:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=rl0iF5cviFU6EQs6YMejuIygE6PayoqDT9PNMzgvCFM=; b=S6Bz5xyjpy/qab HuWtQY7CmP6bfErucLa8z+i03SjhzPbYFUQoO71jIBafQWngfTOqwOIrRBMmDoMttkR1aFFonvVP+ 8U8VUStbi9jHgPA4pWEHLgugKgGCTlXtp1W3FLMhK/m/poZQdJaJK3BsCMH7Q4CWJS5sw4wnFfZ33 eCL9k8Nr6z+UCvloqyi+mMhRLBNlGU5xK3unS2h+uOxgXmLHv3xeos2XgCZnfrJknVDSJc/jr0GZh Yz+keIF6xeJKNGXrBDpkHtQUnS/gGq9qBROb502XhFN9iRKlcgsnfwzOa+EAJLdm2pLZz+Og3kMsr hhhYQ7YNkEtrjqta+idg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tGvuB-0000000H7GR-14ot; Fri, 29 Nov 2024 07:59:11 +0000 Received: from mx0a-0031df01.pphosted.com ([205.220.168.131]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tGvu7-0000000H7Fz-2NkR for linux-phy@lists.infradead.org; Fri, 29 Nov 2024 07:59:09 +0000 Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AT0vdOf028073; Fri, 29 Nov 2024 07:58:58 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= bT5DIr/G4Shwxg5/owo1xod8m/e8igGYEN80Tg987EY=; b=BVfRaJyTNG46whjy 8KYPlAfyQJWVwrz9CIjOEIvD7LB3rfCP8f2/tEoXK8pB1Pmtyidq5owXjK9vWL5I ae7YR93VFnn2PCvnElXIu+kSvETjnffSaaljx6Yk9keImMeV+PFa3zlGNAng/NFo n+LRZ9Ue8aw29xec08GO51vfEq5dvK8CJpxK5oPwbpAkC+C8XQuRQqr0RefN9KqZ ye7e4wQGLGiT4F3gl5c76qzY7YsFeMszj07ng+KkTEP4g/5//eqiAlEAOUbHPwmW sW6mEz2g23Sk/Ff6H4yQPJb4DRKyyhMGg1p8I87/iqln0sL2MvU8JVf5kE8/Vl+9 ynVdgQ== Received: from nasanppmta03.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4366xw4vkj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:58:58 +0000 (GMT) Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA03.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AT7wvOJ030032 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:58:57 GMT Received: from szioemm-lnxbld002.qualcomm.com (10.80.80.8) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 28 Nov 2024 23:58:49 -0800 From: Xiangxu Yin Date: Fri, 29 Nov 2024 15:57:43 +0800 Subject: [PATCH 3/8] phy: qcom: qmp-usbc: Add DP phy mode support on QCS615 MIME-Version: 1.0 Message-ID: <20241129-add-displayport-support-for-qcs615-platform-v1-3-09a4338d93ef@quicinc.com> References: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> In-Reply-To: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> To: Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Kuogee Hsieh , Vinod Koul , Kishon Vijay Abraham I , Linus Walleij , Bartosz Golaszewski , , CC: , , , , , , , Xiangxu Yin X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732867103; l=60212; i=quic_xiangxuy@quicinc.com; s=20241125; h=from:subject:message-id; bh=KGzJV1t1T/YBEJ8gQIuV542U6R3I8+Zp/14yOM14iy4=; b=rjwyQmZJwGUpX7UO2hUkIk8YueZQOhAX61/ApYp4o6h7CSHPDxsC76JB1OqyB406Z3ZzmpCy6 q7djdQKplWsAgIeQhY6z1ej2+lmVD9/6iCtuGl0S1HjE+9ZGPPp7259 X-Developer-Key: i=quic_xiangxuy@quicinc.com; a=ed25519; pk=F1TwipJzpywfbt3n/RPi4l/A4AVF+QC89XzCHgZYaOc= X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: VG4mFIQSI-o_8gJ9sipVVZc-00JLlaEQ X-Proofpoint-ORIG-GUID: VG4mFIQSI-o_8gJ9sipVVZc-00JLlaEQ X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 impostorscore=0 bulkscore=0 adultscore=0 suspectscore=0 mlxlogscore=999 mlxscore=0 spamscore=0 malwarescore=0 lowpriorityscore=0 priorityscore=1501 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2411290064 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241128_235907_665682_92B1E55A X-CRM114-Status: GOOD ( 19.31 ) X-BeenThere: linux-phy@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux Phy Mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-phy" Errors-To: linux-phy-bounces+linux-phy=archiver.kernel.org@lists.infradead.org Extended DP support for QCS615 USB or DP phy. Differentiated between USBC and DP PHY using the match table’s type, dynamically generating different types of cfg and layout attributes during initialization based on this type. Static variables are stored in cfg, while parsed values are organized into the layout structure. Signed-off-by: Xiangxu Yin --- drivers/phy/qualcomm/phy-qcom-qmp-dp-phy.h | 1 + drivers/phy/qualcomm/phy-qcom-qmp-usbc.c | 1453 ++++++++++++++++++++++++---- 2 files changed, 1254 insertions(+), 200 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy.h b/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy.h index 0ebd405bcaf0cac8215550bfc9b226f30cc43a59..59885616405f878885d0837838a0bac1899fb69f 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy.h @@ -25,6 +25,7 @@ #define QSERDES_DP_PHY_AUX_CFG7 0x03c #define QSERDES_DP_PHY_AUX_CFG8 0x040 #define QSERDES_DP_PHY_AUX_CFG9 0x044 +#define QSERDES_DP_PHY_VCO_DIV 0x068 /* QSERDES COM_BIAS_EN_CLKBUFLR_EN bits */ # define QSERDES_V3_COM_BIAS_EN 0x0001 diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c index cf12a6f12134dc77ff032f967b2efa43e3de4b21..7fece9d7dc959ed5a7c62077d8552324c3734859 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c @@ -22,13 +22,20 @@ #include #include #include +#include +#include #include "phy-qcom-qmp-common.h" #include "phy-qcom-qmp.h" #include "phy-qcom-qmp-pcs-misc-v3.h" +#include "phy-qcom-qmp-dp-phy.h" +#include "phy-qcom-qmp-dp-phy-v3.h" + #define PHY_INIT_COMPLETE_TIMEOUT 10000 +#define SW_PORTSELECT_VAL BIT(0) +#define SW_PORTSELECT_MUX BIT(1) /* set of registers with offsets different per-PHY */ enum qphy_reg_layout { @@ -284,7 +291,26 @@ static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), }; -struct qmp_usbc_offsets { +enum qmp_phy_usbc_type { + QMP_PHY_USBC_INVALID, + QMP_PHY_USBC_USB, + QMP_PHY_USBC_DP, +}; + +/* list of regulators */ +struct qmp_regulator_data { + const char *name; + unsigned int enable_load; +}; + +struct dev_cfg { + int type; + const void *cfg; +}; + +struct qmp_usbc; + +struct qmp_usbc_usb_offsets { u16 serdes; u16 pcs; u16 pcs_misc; @@ -295,9 +321,9 @@ struct qmp_usbc_offsets { u16 rx2; }; -/* struct qmp_phy_cfg - per-PHY initialization config */ -struct qmp_phy_cfg { - const struct qmp_usbc_offsets *offsets; +/* struct qmp_phy_usb_cfg - per-usb PHY initialization config */ +struct qmp_phy_usb_cfg { + const struct qmp_usbc_usb_offsets *offsets; /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ const struct qmp_phy_init_tbl *serdes_tbl; @@ -317,11 +343,7 @@ struct qmp_phy_cfg { const unsigned int *regs; }; -struct qmp_usbc { - struct device *dev; - - const struct qmp_phy_cfg *cfg; - +struct qmp_phy_usb_layout { void __iomem *serdes; void __iomem *pcs; void __iomem *pcs_misc; @@ -329,28 +351,67 @@ struct qmp_usbc { void __iomem *rx; void __iomem *tx2; void __iomem *rx2; - struct regmap *tcsr_map; u32 vls_clamp_reg; - + enum phy_mode mode; + struct typec_switch_dev *sw; struct clk *pipe_clk; + struct clk_fixed_rate pipe_clk_fixed; +}; + +struct qmp_usbc_dp_offsets { + u16 dp_serdes; + u16 dp_txa; + u16 dp_txb; + u16 dp_phy; +}; + +/* struct qmp_phy_dp_cfg - per-dp PHY initialization config */ +struct qmp_phy_dp_cfg { + const struct qmp_usbc_dp_offsets *offsets; + + /* DP PHY swing and pre_emphasis tables */ + const u8 (*swing_tbl)[4][4]; + const u8 (*pre_emphasis_tbl)[4][4]; + + // /* DP PHY callbacks */ + int (*dp_aux_init)(struct qmp_usbc *qmp); + int (*configure_dp_serdes)(struct qmp_usbc *qmp); + int (*configure_dp_voltages)(struct qmp_usbc *qmp); + int (*configure_dp_phy)(struct qmp_usbc *qmp); + int (*calibrate_dp_phy)(struct qmp_usbc *qmp); + + const struct qmp_regulator_data *vreg_list; + int num_vregs; +}; + +struct qmp_phy_dp_layout { + void __iomem *dp_phy; + void __iomem *dp_tx; + void __iomem *dp_tx2; + void __iomem *dp_serdes; + struct regmap *tcsr_map; + u32 dp_phy_mode; + unsigned int dp_aux_cfg; + struct phy_configure_opts_dp dp_opts; + struct clk_hw dp_link_hw; + struct clk_hw dp_pixel_hw; +}; + +struct qmp_usbc { + struct device *dev; + int type; struct clk_bulk_data *clks; int num_clks; int num_resets; struct reset_control_bulk_data *resets; struct regulator_bulk_data *vregs; - struct mutex phy_mutex; - - enum phy_mode mode; - unsigned int usb_init_count; - struct phy *phy; - - struct clk_fixed_rate pipe_clk_fixed; - - struct typec_switch_dev *sw; enum typec_orientation orientation; + unsigned int init_count; + const void *cfg; + void *layout; }; static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) @@ -391,12 +452,21 @@ static const char * const usb3phy_reset_l[] = { "phy_phy", "phy", }; +static const char * const dp_usb3phy_reset_l[] = { + "phy", +}; + /* list of regulators */ -static const char * const qmp_phy_vreg_l[] = { +static const char * const qmp_phy_usb_vreg_l[] = { "vdda-phy", "vdda-pll", }; -static const struct qmp_usbc_offsets qmp_usbc_offsets_v3_qcm2290 = { +static struct qmp_regulator_data qmp_phy_dp_vreg_l[] = { + { .name = "vdda-phy", .enable_load = 21800 }, + { .name = "vdda-pll", .enable_load = 36000 }, +}; + +static const struct qmp_usbc_usb_offsets qmp_usbc_usb_offsets_v3_qcm2290 = { .serdes = 0x0, .pcs = 0xc00, .pcs_misc = 0xa00, @@ -406,8 +476,15 @@ static const struct qmp_usbc_offsets qmp_usbc_offsets_v3_qcm2290 = { .rx2 = 0x800, }; -static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { - .offsets = &qmp_usbc_offsets_v3_qcm2290, +static const struct qmp_usbc_dp_offsets qmp_usbc_dp_offsets_qcs615 = { + .dp_serdes = 0x0C00, + .dp_txa = 0x0400, + .dp_txb = 0x0800, + .dp_phy = 0x0000, +}; + +static const struct qmp_phy_usb_cfg msm8998_usb3phy_cfg = { + .offsets = &qmp_usbc_usb_offsets_v3_qcm2290, .serdes_tbl = msm8998_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(msm8998_usb3_serdes_tbl), @@ -417,13 +494,13 @@ static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { .rx_tbl_num = ARRAY_SIZE(msm8998_usb3_rx_tbl), .pcs_tbl = msm8998_usb3_pcs_tbl, .pcs_tbl_num = ARRAY_SIZE(msm8998_usb3_pcs_tbl), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = qmp_phy_usb_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_usb_vreg_l), .regs = qmp_v3_usb3phy_regs_layout, }; -static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = { - .offsets = &qmp_usbc_offsets_v3_qcm2290, +static const struct qmp_phy_usb_cfg qcm2290_usb3phy_cfg = { + .offsets = &qmp_usbc_usb_offsets_v3_qcm2290, .serdes_tbl = qcm2290_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl), @@ -433,13 +510,13 @@ static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = { .rx_tbl_num = ARRAY_SIZE(qcm2290_usb3_rx_tbl), .pcs_tbl = qcm2290_usb3_pcs_tbl, .pcs_tbl_num = ARRAY_SIZE(qcm2290_usb3_pcs_tbl), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = qmp_phy_usb_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_usb_vreg_l), .regs = qmp_v3_usb3phy_regs_layout_qcm2290, }; -static const struct qmp_phy_cfg sdm660_usb3phy_cfg = { - .offsets = &qmp_usbc_offsets_v3_qcm2290, +static const struct qmp_phy_usb_cfg sdm660_usb3phy_cfg = { + .offsets = &qmp_usbc_usb_offsets_v3_qcm2290, .serdes_tbl = qcm2290_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl), @@ -449,20 +526,352 @@ static const struct qmp_phy_cfg sdm660_usb3phy_cfg = { .rx_tbl_num = ARRAY_SIZE(sdm660_usb3_rx_tbl), .pcs_tbl = qcm2290_usb3_pcs_tbl, .pcs_tbl_num = ARRAY_SIZE(qcm2290_usb3_pcs_tbl), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = qmp_phy_usb_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_usb_vreg_l), .regs = qmp_v3_usb3phy_regs_layout_qcm2290, }; -static int qmp_usbc_init(struct phy *phy) +static const u8 qmp_dp_pre_emphasis_hbr2_rbr[4][4] = { + {0x00, 0x0B, 0x12, 0xFF}, /* pe0, 0 db */ + {0x00, 0x0A, 0x12, 0xFF}, /* pe1, 3.5 db */ + {0x00, 0x0C, 0xFF, 0xFF}, /* pe2, 6.0 db */ + {0xFF, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */ +}; + +static const u8 qmp_dp_voltage_swing_hbr2_rbr[4][4] = { + {0x07, 0x0F, 0x14, 0xFF}, /* sw0, 0.4v */ + {0x11, 0x1D, 0x1F, 0xFF}, /* sw1, 0.6 v */ + {0x18, 0x1F, 0xFF, 0xFF}, /* sw1, 0.8 v */ + {0xFF, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */ +}; + +static int qcs615_qmp_dp_aux_init(struct qmp_usbc *qmp); +static int qcs615_qmp_configure_dp_serdes(struct qmp_usbc *qmp); +static int qcs615_qmp_configure_dp_voltages(struct qmp_usbc *qmp); +static int qcs615_qmp_configure_dp_phy(struct qmp_usbc *qmp); +static int qcs615_qmp_calibrate_dp_phy(struct qmp_usbc *qmp); + +static void qmp_usbc_check_dp_phy(struct qmp_usbc *qmp, const char *pos); + +static const struct qmp_phy_dp_cfg qcs615_dpphy_cfg = { + .offsets = &qmp_usbc_dp_offsets_qcs615, + + .swing_tbl = &qmp_dp_voltage_swing_hbr2_rbr, + .pre_emphasis_tbl = &qmp_dp_pre_emphasis_hbr2_rbr, + + .dp_aux_init = qcs615_qmp_dp_aux_init, + .configure_dp_serdes = qcs615_qmp_configure_dp_serdes, + .configure_dp_voltages = qcs615_qmp_configure_dp_voltages, + .configure_dp_phy = qcs615_qmp_configure_dp_phy, + .calibrate_dp_phy = qcs615_qmp_calibrate_dp_phy, + + .vreg_list = qmp_phy_dp_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_dp_vreg_l), +}; + +#define to_usb_cfg(x) ((struct qmp_phy_usb_cfg *)(x->cfg)) +#define to_dp_cfg(x) ((struct qmp_phy_dp_cfg *)(x->cfg)) +#define to_usb_layout(x) ((struct qmp_phy_usb_layout *)(x->layout)) +#define to_dp_layout(x) ((struct qmp_phy_dp_layout *)(x->layout)) + +static int qcs615_qmp_dp_aux_init(struct qmp_usbc *qmp) +{ + struct qmp_phy_dp_layout *layout = to_dp_layout(qmp); + + regmap_write(layout->tcsr_map, layout->dp_phy_mode, 0x1); + + writel(DP_PHY_PD_CTL_AUX_PWRDN | + DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN | + DP_PHY_PD_CTL_PLL_PWRDN, + layout->dp_phy + QSERDES_DP_PHY_PD_CTL); + + writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | + DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN | + DP_PHY_PD_CTL_PLL_PWRDN, + layout->dp_phy + QSERDES_DP_PHY_PD_CTL); + + writel(0x00, layout->dp_phy + QSERDES_DP_PHY_AUX_CFG0); + writel(0x13, layout->dp_phy + QSERDES_DP_PHY_AUX_CFG1); + writel(0x00, layout->dp_phy + QSERDES_DP_PHY_AUX_CFG2); + writel(0x00, layout->dp_phy + QSERDES_DP_PHY_AUX_CFG3); + writel(0x0a, layout->dp_phy + QSERDES_DP_PHY_AUX_CFG4); + writel(0x26, layout->dp_phy + QSERDES_DP_PHY_AUX_CFG5); + writel(0x0a, layout->dp_phy + QSERDES_DP_PHY_AUX_CFG6); + writel(0x03, layout->dp_phy + QSERDES_DP_PHY_AUX_CFG7); + writel(0xbb, layout->dp_phy + QSERDES_DP_PHY_AUX_CFG8); + writel(0x03, layout->dp_phy + QSERDES_DP_PHY_AUX_CFG9); + layout->dp_aux_cfg = 0; + + writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | + PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | + PHY_AUX_REQ_ERR_MASK, + layout->dp_phy + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK); + return 0; +} + +static int qcs615_qmp_configure_dp_serdes(struct qmp_usbc *qmp) +{ + struct qmp_phy_dp_layout *layout = to_dp_layout(qmp); + void __iomem *serdes = layout->dp_serdes; + const struct phy_configure_opts_dp *dp_opts = &layout->dp_opts; + u8 hsclk_sel; + u8 dec_start_mode0; + u8 div_frac_start1_mode0; + u8 div_frac_start2_mode0; + u8 div_frac_start3_mode0; + u8 lock_cmp1_mode0; + u8 lock_cmp2_mode0; + u8 lock_cmp3_mode0; + + switch (dp_opts->link_rate) { + case 1620: + hsclk_sel = 0x2c; + dec_start_mode0 = 0x69; + div_frac_start1_mode0 = 0x00; + div_frac_start2_mode0 = 0x80; + div_frac_start3_mode0 = 0x07; + lock_cmp1_mode0 = 0xbf; + lock_cmp2_mode0 = 0x21; + lock_cmp3_mode0 = 0x00; + break; + case 2700: + hsclk_sel = 0x24; + dec_start_mode0 = 0x69; + div_frac_start1_mode0 = 0x00; + div_frac_start2_mode0 = 0x80; + div_frac_start3_mode0 = 0x07; + lock_cmp1_mode0 = 0x3f; + lock_cmp2_mode0 = 0x38; + lock_cmp3_mode0 = 0x00; + break; + case 5400: + hsclk_sel = 0x20; + dec_start_mode0 = 0x8c; + div_frac_start1_mode0 = 0x00; + div_frac_start2_mode0 = 0x00; + div_frac_start3_mode0 = 0x0a; + lock_cmp1_mode0 = 0x7f; + lock_cmp2_mode0 = 0x70; + lock_cmp3_mode0 = 0x00; + break; + default: + /* Other link rates aren't supported */ + return -EINVAL; + } + + writel(0x01, serdes + QSERDES_COM_SVS_MODE_CLK_SEL); + writel(0x37, serdes + QSERDES_COM_SYSCLK_EN_SEL); + writel(0x00, serdes + QSERDES_COM_CLK_SELECT); + writel(0x06, serdes + QSERDES_COM_SYS_CLK_CTRL); + writel(0x3f, serdes + QSERDES_COM_BIAS_EN_CLKBUFLR_EN); + writel(0x0e, serdes + QSERDES_COM_CLK_ENABLE1); + writel(0x0f, serdes + QSERDES_COM_BG_CTRL); + writel(0x06, serdes + QSERDES_COM_SYSCLK_BUF_ENABLE); + writel(0x30, serdes + QSERDES_COM_CLK_SELECT); + writel(0x0f, serdes + QSERDES_COM_PLL_IVCO); + writel(0x28, serdes + QSERDES_COM_PLL_CCTRL_MODE0); + writel(0x16, serdes + QSERDES_COM_PLL_RCTRL_MODE0); + writel(0x0b, serdes + QSERDES_COM_CP_CTRL_MODE0); + + writel(hsclk_sel, serdes + QSERDES_COM_HSCLK_SEL); + writel(dec_start_mode0, serdes + QSERDES_COM_DEC_START_MODE0); + writel(div_frac_start1_mode0, serdes + QSERDES_COM_DIV_FRAC_START1_MODE0); + writel(div_frac_start2_mode0, serdes + QSERDES_COM_DIV_FRAC_START2_MODE0); + writel(div_frac_start3_mode0, serdes + QSERDES_COM_DIV_FRAC_START3_MODE0); + writel(lock_cmp1_mode0, serdes + QSERDES_COM_LOCK_CMP1_MODE0); + writel(lock_cmp2_mode0, serdes + QSERDES_COM_LOCK_CMP2_MODE0); + writel(lock_cmp3_mode0, serdes + QSERDES_COM_LOCK_CMP3_MODE0); + + writel(0x40, serdes + QSERDES_COM_INTEGLOOP_GAIN0_MODE0); + writel(0x00, serdes + QSERDES_COM_INTEGLOOP_GAIN1_MODE0); + writel(0x00, serdes + QSERDES_COM_VCO_TUNE_MAP); + writel(0x08, serdes + QSERDES_COM_BG_TIMER); + writel(0x05, serdes + QSERDES_COM_CORECLK_DIV); + writel(0x00, serdes + QSERDES_COM_VCO_TUNE_CTRL); + writel(0x00, serdes + QSERDES_COM_VCO_TUNE1_MODE0); + writel(0x00, serdes + QSERDES_COM_VCO_TUNE2_MODE0); + writel(0x00, serdes + QSERDES_COM_VCO_TUNE_CTRL); + + writel(0x0f, serdes + QSERDES_COM_CORE_CLK_EN); + + return 0; +} + +static int qcs615_qmp_configure_dp_voltages(struct qmp_usbc *qmp) +{ + struct qmp_phy_dp_layout *layout = to_dp_layout(qmp); + struct qmp_phy_dp_cfg *cfg = to_dp_cfg(qmp); + const struct phy_configure_opts_dp *dp_opts = &layout->dp_opts; + void __iomem *tx = layout->dp_tx; + void __iomem *tx2 = layout->dp_tx2; + unsigned int v_level = 0, p_level = 0; + u8 voltage_swing_cfg, pre_emphasis_cfg; + int i; + + if (dp_opts->lanes > 4) { + dev_err(qmp->dev, "Invalid lane_num(%d)\n", dp_opts->lanes); + return -EINVAL; + } + + for (i = 0; i < dp_opts->lanes; i++) { + v_level = max(v_level, dp_opts->voltage[i]); + p_level = max(p_level, dp_opts->pre[i]); + } + + if ((v_level > 4) || (pre_emphasis_cfg > 4)) { + dev_err(qmp->dev, "Invalid v(%d) | p(%d) level)\n", + v_level, pre_emphasis_cfg); + return -EINVAL; + } + + voltage_swing_cfg = (*cfg->swing_tbl)[v_level][p_level]; + pre_emphasis_cfg = (*cfg->pre_emphasis_tbl)[v_level][p_level]; + + /* Enable MUX to use Cursor values from these registers */ + voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN; + pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN; + + if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF) + return -EINVAL; + + /* program default setting first */ + writel(0x2A, tx + QSERDES_V3_TX_TX_DRV_LVL); + writel(0x20, tx + QSERDES_V3_TX_TX_EMP_POST1_LVL); + writel(0x2A, tx2 + QSERDES_V3_TX_TX_DRV_LVL); + writel(0x20, tx2 + QSERDES_V3_TX_TX_EMP_POST1_LVL); + + writel(voltage_swing_cfg, tx + QSERDES_V3_TX_TX_DRV_LVL); + writel(pre_emphasis_cfg, tx + QSERDES_V3_TX_TX_EMP_POST1_LVL); + writel(voltage_swing_cfg, tx2 + QSERDES_V3_TX_TX_DRV_LVL); + writel(pre_emphasis_cfg, tx2 + QSERDES_V3_TX_TX_EMP_POST1_LVL); + + return 0; +} + +static int qcs615_qmp_configure_dp_phy(struct qmp_usbc *qmp) +{ + struct qmp_phy_dp_layout *layout = to_dp_layout(qmp); + u32 status; + + writel(0x01, layout->dp_phy + QSERDES_DP_PHY_CFG); + writel(0x05, layout->dp_phy + QSERDES_DP_PHY_CFG); + writel(0x01, layout->dp_phy + QSERDES_DP_PHY_CFG); + writel(0x09, layout->dp_phy + QSERDES_DP_PHY_CFG); + + writel(0x20, layout->dp_serdes + QSERDES_COM_RESETSM_CNTRL); + + // C_READY + if (readl_poll_timeout(layout->dp_serdes + QSERDES_COM_C_READY_STATUS, + status, + ((status & BIT(0)) > 0), + 500, + 10000)) { + dev_err(qmp->dev, "C_READY not ready\n"); + return -ETIMEDOUT; + } + + // FREQ_DONE + if (readl_poll_timeout(layout->dp_serdes + QSERDES_COM_CMN_STATUS, + status, + ((status & BIT(0)) > 0), + 500, + 10000)){ + dev_err(qmp->dev, "FREQ_DONE not ready\n"); + return -ETIMEDOUT; + } + + // PLL_LOCKED + if (readl_poll_timeout(layout->dp_serdes + QSERDES_COM_CMN_STATUS, + status, + ((status & BIT(1)) > 0), + 500, + 10000)){ + dev_err(qmp->dev, "PLL_LOCKED not ready\n"); + return -ETIMEDOUT; + } + + writel(0x19, layout->dp_phy + QSERDES_DP_PHY_CFG); + udelay(10); + + // TSYNC_DONE + if (readl_poll_timeout(layout->dp_phy + QSERDES_V3_DP_PHY_STATUS, + status, + ((status & BIT(0)) > 0), + 500, + 10000)){ + dev_err(qmp->dev, "TSYNC_DONE not ready\n"); + return -ETIMEDOUT; + } + + // PHY_READY + if (readl_poll_timeout(layout->dp_phy + QSERDES_V3_DP_PHY_STATUS, + status, + ((status & BIT(1)) > 0), + 500, + 10000)){ + dev_err(qmp->dev, "PHY_READY not ready\n"); + return -ETIMEDOUT; + } + + writel(0x3f, layout->dp_tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); + writel(0x10, layout->dp_tx + QSERDES_V3_TX_HIGHZ_DRVR_EN); + writel(0x0a, layout->dp_tx + QSERDES_V3_TX_TX_POL_INV); + writel(0x3f, layout->dp_tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); + writel(0x10, layout->dp_tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN); + writel(0x0a, layout->dp_tx2 + QSERDES_V3_TX_TX_POL_INV); + + writel(0x18, layout->dp_phy + QSERDES_DP_PHY_CFG); + writel(0x19, layout->dp_phy + QSERDES_DP_PHY_CFG); + + if (readl_poll_timeout(layout->dp_phy + QSERDES_V3_DP_PHY_STATUS, + status, + ((status & BIT(1)) > 0), + 500, + 10000)){ + dev_err(qmp->dev, "PHY_READY not ready\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int qcs615_qmp_calibrate_dp_phy(struct qmp_usbc *qmp) +{ + static const u8 cfg1_settings[] = {0x13, 0x23, 0x1d}; + struct qmp_phy_dp_layout *layout = to_dp_layout(qmp); + u8 val; + + layout->dp_aux_cfg++; + layout->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); + val = cfg1_settings[layout->dp_aux_cfg]; + + writel(val, layout->dp_phy + QSERDES_DP_PHY_AUX_CFG1); + + qmp_usbc_check_dp_phy(qmp, "pos_calibrate"); + + return 0; +} + +static int qmp_usbc_com_init(struct phy *phy) { struct qmp_usbc *qmp = phy_get_drvdata(phy); - const struct qmp_phy_cfg *cfg = qmp->cfg; - void __iomem *pcs = qmp->pcs; + int num_vregs; u32 val = 0; int ret; + unsigned int reg_pwr_dn; - ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); + if (qmp->type == QMP_PHY_USBC_USB) { + struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp); + + num_vregs = cfg->num_vregs; + reg_pwr_dn = cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]; + } else { + struct qmp_phy_dp_cfg *cfg = to_dp_cfg(qmp); + + num_vregs = cfg->num_vregs; + } + + ret = regulator_bulk_enable(num_vregs, qmp->vregs); if (ret) { dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); return ret; @@ -484,73 +893,85 @@ static int qmp_usbc_init(struct phy *phy) if (ret) goto err_assert_reset; - qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN); - -#define SW_PORTSELECT_VAL BIT(0) -#define SW_PORTSELECT_MUX BIT(1) /* Use software based port select and switch on typec orientation */ val = SW_PORTSELECT_MUX; if (qmp->orientation == TYPEC_ORIENTATION_REVERSE) val |= SW_PORTSELECT_VAL; - writel(val, qmp->pcs_misc); + + if (qmp->type == QMP_PHY_USBC_USB) { + struct qmp_phy_usb_layout *layout = to_usb_layout(qmp); + + qphy_setbits(layout->pcs, reg_pwr_dn, SW_PWRDN); + writel(val, layout->pcs_misc); + } return 0; err_assert_reset: reset_control_bulk_assert(qmp->num_resets, qmp->resets); err_disable_regulators: - regulator_bulk_disable(cfg->num_vregs, qmp->vregs); + regulator_bulk_disable(num_vregs, qmp->vregs); return ret; } -static int qmp_usbc_exit(struct phy *phy) +static int qmp_usbc_com_exit(struct phy *phy) { struct qmp_usbc *qmp = phy_get_drvdata(phy); - const struct qmp_phy_cfg *cfg = qmp->cfg; + int num_vregs; reset_control_bulk_assert(qmp->num_resets, qmp->resets); clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks); - regulator_bulk_disable(cfg->num_vregs, qmp->vregs); + if (qmp->type == QMP_PHY_USBC_USB) { + struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp); + + num_vregs = cfg->num_vregs; + } else { + struct qmp_phy_dp_cfg *cfg = to_dp_cfg(qmp); + + num_vregs = cfg->num_vregs; + } + regulator_bulk_disable(num_vregs, qmp->vregs); return 0; } -static int qmp_usbc_power_on(struct phy *phy) +static int qmp_usbc_usb_power_on(struct phy *phy) { struct qmp_usbc *qmp = phy_get_drvdata(phy); - const struct qmp_phy_cfg *cfg = qmp->cfg; + const struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp); + struct qmp_phy_usb_layout *layout = to_usb_layout(qmp); void __iomem *status; unsigned int val; int ret; - qmp_configure(qmp->dev, qmp->serdes, cfg->serdes_tbl, + qmp_configure(qmp->dev, layout->serdes, cfg->serdes_tbl, cfg->serdes_tbl_num); - ret = clk_prepare_enable(qmp->pipe_clk); + ret = clk_prepare_enable(layout->pipe_clk); if (ret) { dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret); return ret; } /* Tx, Rx, and PCS configurations */ - qmp_configure_lane(qmp->dev, qmp->tx, cfg->tx_tbl, cfg->tx_tbl_num, 1); - qmp_configure_lane(qmp->dev, qmp->rx, cfg->rx_tbl, cfg->rx_tbl_num, 1); + qmp_configure_lane(qmp->dev, layout->tx, cfg->tx_tbl, cfg->tx_tbl_num, 1); + qmp_configure_lane(qmp->dev, layout->rx, cfg->rx_tbl, cfg->rx_tbl_num, 1); - qmp_configure_lane(qmp->dev, qmp->tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2); - qmp_configure_lane(qmp->dev, qmp->rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2); + qmp_configure_lane(qmp->dev, layout->tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2); + qmp_configure_lane(qmp->dev, layout->rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2); - qmp_configure(qmp->dev, qmp->pcs, cfg->pcs_tbl, cfg->pcs_tbl_num); + qmp_configure(qmp->dev, layout->pcs, cfg->pcs_tbl, cfg->pcs_tbl_num); /* Pull PHY out of reset state */ - qphy_clrbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); + qphy_clrbits(layout->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); /* start SerDes and Phy-Coding-Sublayer */ - qphy_setbits(qmp->pcs, cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START); + qphy_setbits(layout->pcs, cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START); - status = qmp->pcs + cfg->regs[QPHY_PCS_STATUS]; + status = layout->pcs + cfg->regs[QPHY_PCS_STATUS]; ret = readl_poll_timeout(status, val, !(val & PHYSTATUS), 200, PHY_INIT_COMPLETE_TIMEOUT); if (ret) { @@ -561,92 +982,348 @@ static int qmp_usbc_power_on(struct phy *phy) return 0; err_disable_pipe_clk: - clk_disable_unprepare(qmp->pipe_clk); + clk_disable_unprepare(layout->pipe_clk); return ret; } -static int qmp_usbc_power_off(struct phy *phy) +static int qmp_usbc_usb_power_off(struct phy *phy) { struct qmp_usbc *qmp = phy_get_drvdata(phy); - const struct qmp_phy_cfg *cfg = qmp->cfg; + const struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp); + struct qmp_phy_usb_layout *layout = to_usb_layout(qmp); - clk_disable_unprepare(qmp->pipe_clk); + clk_disable_unprepare(layout->pipe_clk); /* PHY reset */ - qphy_setbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); + qphy_setbits(layout->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); /* stop SerDes and Phy-Coding-Sublayer */ - qphy_clrbits(qmp->pcs, cfg->regs[QPHY_START_CTRL], + qphy_clrbits(layout->pcs, cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START); /* Put PHY into POWER DOWN state: active low */ - qphy_clrbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], + qphy_clrbits(layout->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN); return 0; } -static int qmp_usbc_enable(struct phy *phy) +static int qmp_usbc_usb_enable(struct phy *phy) { struct qmp_usbc *qmp = phy_get_drvdata(phy); int ret; mutex_lock(&qmp->phy_mutex); - ret = qmp_usbc_init(phy); + ret = qmp_usbc_com_init(phy); if (ret) goto out_unlock; - ret = qmp_usbc_power_on(phy); + ret = qmp_usbc_usb_power_on(phy); if (ret) { - qmp_usbc_exit(phy); + qmp_usbc_com_exit(phy); goto out_unlock; } - qmp->usb_init_count++; + qmp->init_count++; out_unlock: mutex_unlock(&qmp->phy_mutex); return ret; } -static int qmp_usbc_disable(struct phy *phy) +static int qmp_usbc_usb_disable(struct phy *phy) { struct qmp_usbc *qmp = phy_get_drvdata(phy); int ret; - qmp->usb_init_count--; - ret = qmp_usbc_power_off(phy); + qmp->init_count--; + ret = qmp_usbc_usb_power_off(phy); if (ret) return ret; - return qmp_usbc_exit(phy); + return qmp_usbc_com_exit(phy); +} + +static int qmp_usbc_usb_set_mode(struct phy *phy, enum phy_mode mode, int submode) +{ + struct qmp_usbc *qmp = phy_get_drvdata(phy); + struct qmp_phy_usb_layout *layout = to_usb_layout(qmp); + + layout->mode = mode; + + return 0; +} + +static int qmp_usbc_dp_init(struct phy *phy) +{ + struct qmp_usbc *qmp = phy_get_drvdata(phy); + const struct qmp_phy_dp_cfg *cfg = to_dp_cfg(qmp); + int ret; + + if (qmp->init_count) { + dev_err(qmp->dev, "type(%d) inited(%d)\n", qmp->type, qmp->init_count); + return 0; + } + + mutex_lock(&qmp->phy_mutex); + + ret = qmp_usbc_com_init(phy); + if (ret) { + dev_err(qmp->dev, "type(%d) com_init fail\n", qmp->type); + goto dp_init_unlock; + } + + cfg->dp_aux_init(qmp); + + qmp->init_count++; + +dp_init_unlock: + mutex_unlock(&qmp->phy_mutex); + return ret; +} + +static int qmp_usbc_dp_exit(struct phy *phy) +{ + struct qmp_usbc *qmp = phy_get_drvdata(phy); + + mutex_lock(&qmp->phy_mutex); + + qmp_usbc_com_exit(phy); + + qmp->init_count--; + + mutex_unlock(&qmp->phy_mutex); + + return 0; +} + +static int qmp_usbc_dp_configure(struct phy *phy, union phy_configure_opts *opts) +{ + const struct phy_configure_opts_dp *dp_opts = &opts->dp; + struct qmp_usbc *qmp = phy_get_drvdata(phy); + struct qmp_phy_dp_cfg *cfg = to_dp_cfg(qmp); + struct qmp_phy_dp_layout *layout = to_dp_layout(qmp); + int ret; + + mutex_lock(&qmp->phy_mutex); + + memcpy(&layout->dp_opts, dp_opts, sizeof(*dp_opts)); + if (layout->dp_opts.set_voltages) { + ret = cfg->configure_dp_voltages(qmp); + if (ret) { + dev_err(qmp->dev, "type(%d) err(%d)\n", qmp->type, ret); + mutex_unlock(&qmp->phy_mutex); + return ret; + } + + layout->dp_opts.set_voltages = 0; + } + + mutex_unlock(&qmp->phy_mutex); + + return 0; +} + +static int qmp_usbc_dp_calibrate(struct phy *phy) +{ + struct qmp_usbc *qmp = phy_get_drvdata(phy); + struct qmp_phy_dp_cfg *cfg = to_dp_cfg(qmp); + int ret = 0; + + mutex_lock(&qmp->phy_mutex); + + if (cfg->calibrate_dp_phy) { + ret = cfg->calibrate_dp_phy(qmp); + if (ret) { + dev_err(qmp->dev, "type(%d) err(%d)\n", qmp->type, ret); + mutex_unlock(&qmp->phy_mutex); + return ret; + } + } + + mutex_unlock(&qmp->phy_mutex); + return 0; } -static int qmp_usbc_set_mode(struct phy *phy, enum phy_mode mode, int submode) +static int qmp_usbc_configure_dp_clocks(struct qmp_usbc *qmp) +{ + struct qmp_phy_dp_layout *layout = to_dp_layout(qmp); + const struct phy_configure_opts_dp *dp_opts = &layout->dp_opts; + u32 phy_vco_div; + unsigned long pixel_freq; + + switch (dp_opts->link_rate) { + case 1620: + phy_vco_div = 0x1; + pixel_freq = 1620000000UL / 2; + break; + case 2700: + phy_vco_div = 0x1; + pixel_freq = 2700000000UL / 2; + break; + case 5400: + phy_vco_div = 0x2; + pixel_freq = 5400000000UL / 4; + break; + case 8100: + phy_vco_div = 0x0; + pixel_freq = 8100000000UL / 6; + break; + default: + /* Other link rates aren't supported */ + return -EINVAL; + } + writel(phy_vco_div, layout->dp_phy + QSERDES_DP_PHY_VCO_DIV); + + clk_set_rate(layout->dp_link_hw.clk, dp_opts->link_rate * 100000); + clk_set_rate(layout->dp_pixel_hw.clk, pixel_freq); + + return 0; +} + +static void qmp_usbc_check_dp_phy(struct qmp_usbc *qmp, const char *pos) +{ + struct qmp_phy_dp_layout *layout = to_dp_layout(qmp); + u8 c_ready, cmn_status, phy_status; + + c_ready = readl(layout->dp_serdes + QSERDES_COM_C_READY_STATUS); + cmn_status = readl(layout->dp_serdes + QSERDES_COM_CMN_STATUS); + phy_status = readl(layout->dp_phy + QSERDES_V3_DP_PHY_STATUS); + + dev_dbg(qmp->dev, "pos(%s) c_ready(0x%x) cmn_status(0x%x) phy_status(0x%x)\n", + pos, c_ready, cmn_status, phy_status); +} + +static int qmp_usbc_dp_power_on(struct phy *phy) +{ + struct qmp_usbc *qmp = phy_get_drvdata(phy); + const struct qmp_phy_dp_cfg *cfg = to_dp_cfg(qmp); + struct qmp_phy_dp_layout *layout = to_dp_layout(qmp); + const struct phy_configure_opts_dp *dp_opts = &layout->dp_opts; + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); + void __iomem *tx = layout->dp_tx; + void __iomem *tx2 = layout->dp_tx2; + u8 lane_mode_1; + int ret = 0; + + mutex_lock(&qmp->phy_mutex); + + writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | + DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN | + DP_PHY_PD_CTL_PLL_PWRDN, + layout->dp_phy + QSERDES_DP_PHY_PD_CTL); + + ret = cfg->configure_dp_serdes(qmp); + if (ret) { + dev_err(qmp->dev, "failed to config pll\n"); + goto power_on_unlock; + } + + if (dp_opts->link_rate >= 2700) + lane_mode_1 = 0xc4; + else + lane_mode_1 = 0xc6; + + writel(lane_mode_1, tx + QSERDES_V3_TX_LANE_MODE_1); + writel(lane_mode_1, tx2 + QSERDES_V3_TX_LANE_MODE_1); + + if (reverse) + writel(0xc9, layout->dp_phy + QSERDES_DP_PHY_MODE); + else + writel(0xd9, layout->dp_phy + QSERDES_DP_PHY_MODE); + + writel(0x05, layout->dp_phy + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL); + writel(0x05, layout->dp_phy + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL); + + writel(0x1a, tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); + writel(0x40, tx + QSERDES_V3_TX_VMODE_CTRL1); + writel(0x30, tx + QSERDES_V3_TX_PRE_STALL_LDO_BOOST_EN); + writel(0x3d, tx + QSERDES_V3_TX_INTERFACE_SELECT); + writel(0x0f, tx + QSERDES_V3_TX_CLKBUF_ENABLE); + writel(0x03, tx + QSERDES_V3_TX_RESET_TSYNC_EN); + writel(0x03, tx + QSERDES_V3_TX_TRAN_DRVR_EMP_EN); + writel(0x00, tx + QSERDES_V3_TX_PARRATE_REC_DETECT_IDLE_EN); + writel(0x00, tx + QSERDES_V3_TX_TX_INTERFACE_MODE); + writel(0x2b, tx + QSERDES_V3_TX_TX_EMP_POST1_LVL); + writel(0x2f, tx + QSERDES_V3_TX_TX_DRV_LVL); + writel(0x04, tx + QSERDES_V3_TX_TX_BAND); + writel(0x12, tx + QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX); + writel(0x12, tx + QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX); + + writel(0x1a, tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); + writel(0x40, tx2 + QSERDES_V3_TX_VMODE_CTRL1); + writel(0x30, tx2 + QSERDES_V3_TX_PRE_STALL_LDO_BOOST_EN); + writel(0x3d, tx2 + QSERDES_V3_TX_INTERFACE_SELECT); + writel(0x0f, tx2 + QSERDES_V3_TX_CLKBUF_ENABLE); + writel(0x03, tx2 + QSERDES_V3_TX_RESET_TSYNC_EN); + writel(0x03, tx2 + QSERDES_V3_TX_TRAN_DRVR_EMP_EN); + writel(0x00, tx2 + QSERDES_V3_TX_PARRATE_REC_DETECT_IDLE_EN); + writel(0x00, tx2 + QSERDES_V3_TX_TX_INTERFACE_MODE); + writel(0x2b, tx2 + QSERDES_V3_TX_TX_EMP_POST1_LVL); + writel(0x2f, tx2 + QSERDES_V3_TX_TX_DRV_LVL); + writel(0x04, tx2 + QSERDES_V3_TX_TX_BAND); + writel(0x12, tx2 + QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX); + writel(0x12, tx2 + QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX); + + writel(0x02, layout->dp_serdes + QSERDES_COM_CMN_CONFIG); + qmp_usbc_configure_dp_clocks(qmp); + + ret = cfg->configure_dp_phy(qmp); + if (ret) { + dev_err(qmp->dev, "failed to config dp phy\n"); + goto power_on_unlock; + } + + qmp_usbc_check_dp_phy(qmp, "usbc_dp_power_on_finish"); + +power_on_unlock: + mutex_unlock(&qmp->phy_mutex); + + return ret; +} + +static int qmp_usbc_dp_power_off(struct phy *phy) { struct qmp_usbc *qmp = phy_get_drvdata(phy); + struct qmp_phy_dp_layout *layout = to_dp_layout(qmp); + + mutex_lock(&qmp->phy_mutex); - qmp->mode = mode; + /* Assert DP PHY power down */ + writel(DP_PHY_PD_CTL_PSR_PWRDN, layout->dp_phy + QSERDES_DP_PHY_PD_CTL); + + mutex_unlock(&qmp->phy_mutex); return 0; } -static const struct phy_ops qmp_usbc_phy_ops = { - .init = qmp_usbc_enable, - .exit = qmp_usbc_disable, - .set_mode = qmp_usbc_set_mode, +static const struct phy_ops qmp_usbc_usb_phy_ops = { + .init = qmp_usbc_usb_enable, + .exit = qmp_usbc_usb_disable, + .set_mode = qmp_usbc_usb_set_mode, + .owner = THIS_MODULE, +}; + +static const struct phy_ops qmp_usbc_dp_phy_ops = { + .init = qmp_usbc_dp_init, + .exit = qmp_usbc_dp_exit, + .configure = qmp_usbc_dp_configure, + .calibrate = qmp_usbc_dp_calibrate, + .power_on = qmp_usbc_dp_power_on, + .power_off = qmp_usbc_dp_power_off, .owner = THIS_MODULE, }; static void qmp_usbc_enable_autonomous_mode(struct qmp_usbc *qmp) { - const struct qmp_phy_cfg *cfg = qmp->cfg; - void __iomem *pcs = qmp->pcs; + const struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp); + struct qmp_phy_usb_layout *layout = to_usb_layout(qmp); + void __iomem *pcs = layout->pcs; u32 intr_mask; - if (qmp->mode == PHY_MODE_USB_HOST_SS || - qmp->mode == PHY_MODE_USB_DEVICE_SS) + if (layout->mode == PHY_MODE_USB_HOST_SS || + layout->mode == PHY_MODE_USB_DEVICE_SS) intr_mask = ARCVR_DTCT_EN | ALFPS_DTCT_EN; else intr_mask = ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL; @@ -663,18 +1340,19 @@ static void qmp_usbc_enable_autonomous_mode(struct qmp_usbc *qmp) qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask); /* Enable i/o clamp_n for autonomous mode */ - if (qmp->tcsr_map && qmp->vls_clamp_reg) - regmap_write(qmp->tcsr_map, qmp->vls_clamp_reg, 1); + if (layout->tcsr_map && layout->vls_clamp_reg) + regmap_write(layout->tcsr_map, layout->vls_clamp_reg, 1); } static void qmp_usbc_disable_autonomous_mode(struct qmp_usbc *qmp) { - const struct qmp_phy_cfg *cfg = qmp->cfg; - void __iomem *pcs = qmp->pcs; + const struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp); + struct qmp_phy_usb_layout *layout = to_usb_layout(qmp); + void __iomem *pcs = layout->pcs; /* Disable i/o clamp_n on resume for normal mode */ - if (qmp->tcsr_map && qmp->vls_clamp_reg) - regmap_write(qmp->tcsr_map, qmp->vls_clamp_reg, 0); + if (layout->tcsr_map && layout->vls_clamp_reg) + regmap_write(layout->tcsr_map, layout->vls_clamp_reg, 0); qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL | ALFPS_DTCT_EN); @@ -688,16 +1366,19 @@ static int __maybe_unused qmp_usbc_runtime_suspend(struct device *dev) { struct qmp_usbc *qmp = dev_get_drvdata(dev); - dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->mode); - if (!qmp->phy->init_count) { dev_vdbg(dev, "PHY not initialized, bailing out\n"); return 0; } - qmp_usbc_enable_autonomous_mode(qmp); + if (qmp->type == QMP_PHY_USBC_USB) { + struct qmp_phy_usb_layout *layout = to_usb_layout(qmp); + + dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", layout->mode); + qmp_usbc_enable_autonomous_mode(qmp); + clk_disable_unprepare(layout->pipe_clk); + } - clk_disable_unprepare(qmp->pipe_clk); clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks); return 0; @@ -708,8 +1389,6 @@ static int __maybe_unused qmp_usbc_runtime_resume(struct device *dev) struct qmp_usbc *qmp = dev_get_drvdata(dev); int ret = 0; - dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->mode); - if (!qmp->phy->init_count) { dev_vdbg(dev, "PHY not initialized, bailing out\n"); return 0; @@ -719,14 +1398,19 @@ static int __maybe_unused qmp_usbc_runtime_resume(struct device *dev) if (ret) return ret; - ret = clk_prepare_enable(qmp->pipe_clk); - if (ret) { - dev_err(dev, "pipe_clk enable failed, err=%d\n", ret); - clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks); - return ret; - } + if (qmp->type == QMP_PHY_USBC_USB) { + struct qmp_phy_usb_layout *layout = to_usb_layout(qmp); - qmp_usbc_disable_autonomous_mode(qmp); + dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", layout->mode); + ret = clk_prepare_enable(layout->pipe_clk); + if (ret) { + dev_err(dev, "pipe_clk enable failed, err=%d\n", ret); + clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks); + return ret; + } + + qmp_usbc_disable_autonomous_mode(qmp); + } return 0; } @@ -738,19 +1422,54 @@ static const struct dev_pm_ops qmp_usbc_pm_ops = { static int qmp_usbc_vreg_init(struct qmp_usbc *qmp) { - const struct qmp_phy_cfg *cfg = qmp->cfg; struct device *dev = qmp->dev; - int num = cfg->num_vregs; - int i; + int ret, i; - qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); - if (!qmp->vregs) - return -ENOMEM; + if (qmp->type == QMP_PHY_USBC_USB) { + struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp); + int num = cfg->num_vregs; - for (i = 0; i < num; i++) - qmp->vregs[i].supply = cfg->vreg_list[i]; + qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); + if (!qmp->vregs) + return -ENOMEM; + + for (i = 0; i < num; i++) + qmp->vregs[i].supply = cfg->vreg_list[i]; - return devm_regulator_bulk_get(dev, num, qmp->vregs); + ret = devm_regulator_bulk_get(dev, num, qmp->vregs); + if (ret) { + dev_err(dev, "failed at devm_regulator_bulk_get\n"); + return ret; + } + } else { + struct qmp_phy_dp_cfg *cfg = to_dp_cfg(qmp); + int num = cfg->num_vregs; + + qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); + if (!qmp->vregs) + return -ENOMEM; + + for (i = 0; i < num; i++) + qmp->vregs[i].supply = cfg->vreg_list[i].name; + + ret = devm_regulator_bulk_get(dev, num, qmp->vregs); + if (ret) { + dev_err(dev, "failed at devm_regulator_bulk_get\n"); + return ret; + } + + for (i = 0; i < num; i++) { + ret = regulator_set_load(qmp->vregs[i].consumer, + cfg->vreg_list[i].enable_load); + if (ret) { + dev_err(dev, "failed to set load at %s\n", + qmp->vregs[i].supply); + return ret; + } + } + } + + return 0; } static int qmp_usbc_reset_init(struct qmp_usbc *qmp, @@ -821,7 +1540,9 @@ static void phy_clk_release_provider(void *res) */ static int phy_pipe_clk_register(struct qmp_usbc *qmp, struct device_node *np) { - struct clk_fixed_rate *fixed = &qmp->pipe_clk_fixed; + struct qmp_phy_usb_layout *layout = to_usb_layout(qmp); + + struct clk_fixed_rate *fixed = &layout->pipe_clk_fixed; struct clk_init_data init = { }; int ret; @@ -864,12 +1585,12 @@ static int qmp_usbc_typec_switch_set(struct typec_switch_dev *sw, mutex_lock(&qmp->phy_mutex); qmp->orientation = orientation; - if (qmp->usb_init_count) { - qmp_usbc_power_off(qmp->phy); - qmp_usbc_exit(qmp->phy); + if (qmp->init_count) { + qmp_usbc_usb_power_off(qmp->phy); + qmp_usbc_com_exit(qmp->phy); - qmp_usbc_init(qmp->phy); - qmp_usbc_power_on(qmp->phy); + qmp_usbc_com_init(qmp->phy); + qmp_usbc_usb_power_on(qmp->phy); } mutex_unlock(&qmp->phy_mutex); @@ -880,22 +1601,24 @@ static int qmp_usbc_typec_switch_set(struct typec_switch_dev *sw, static void qmp_usbc_typec_unregister(void *data) { struct qmp_usbc *qmp = data; + struct qmp_phy_usb_layout *layout = to_usb_layout(qmp); - typec_switch_unregister(qmp->sw); + typec_switch_unregister(layout->sw); } static int qmp_usbc_typec_switch_register(struct qmp_usbc *qmp) { struct typec_switch_desc sw_desc = {}; struct device *dev = qmp->dev; + struct qmp_phy_usb_layout *layout = to_usb_layout(qmp); sw_desc.drvdata = qmp; sw_desc.fwnode = dev->fwnode; sw_desc.set = qmp_usbc_typec_switch_set; - qmp->sw = typec_switch_register(dev, &sw_desc); - if (IS_ERR(qmp->sw)) { - dev_err(dev, "Unable to register typec switch: %pe\n", qmp->sw); - return PTR_ERR(qmp->sw); + layout->sw = typec_switch_register(dev, &sw_desc); + if (IS_ERR(layout->sw)) { + dev_err(dev, "Unable to register typec switch: %pe\n", layout->sw); + return PTR_ERR(layout->sw); } return devm_add_action_or_reset(dev, qmp_usbc_typec_unregister, qmp); @@ -907,15 +1630,16 @@ static int qmp_usbc_typec_switch_register(struct qmp_usbc *qmp) } #endif -static int qmp_usbc_parse_dt_legacy(struct qmp_usbc *qmp, struct device_node *np) +static int qmp_usbc_parse_usb_dt_legacy(struct qmp_usbc *qmp, struct device_node *np) { struct platform_device *pdev = to_platform_device(qmp->dev); struct device *dev = qmp->dev; + struct qmp_phy_usb_layout *layout = to_usb_layout(qmp); int ret; - qmp->serdes = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(qmp->serdes)) - return PTR_ERR(qmp->serdes); + layout->serdes = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(layout->serdes)) + return PTR_ERR(layout->serdes); /* * Get memory resources for the PHY: @@ -923,35 +1647,35 @@ static int qmp_usbc_parse_dt_legacy(struct qmp_usbc *qmp, struct device_node *np * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 * For single lane PHYs: pcs_misc (optional) -> 3. */ - qmp->tx = devm_of_iomap(dev, np, 0, NULL); - if (IS_ERR(qmp->tx)) - return PTR_ERR(qmp->tx); + layout->tx = devm_of_iomap(dev, np, 0, NULL); + if (IS_ERR(layout->tx)) + return PTR_ERR(layout->tx); - qmp->rx = devm_of_iomap(dev, np, 1, NULL); - if (IS_ERR(qmp->rx)) - return PTR_ERR(qmp->rx); + layout->rx = devm_of_iomap(dev, np, 1, NULL); + if (IS_ERR(layout->rx)) + return PTR_ERR(layout->rx); - qmp->pcs = devm_of_iomap(dev, np, 2, NULL); - if (IS_ERR(qmp->pcs)) - return PTR_ERR(qmp->pcs); + layout->pcs = devm_of_iomap(dev, np, 2, NULL); + if (IS_ERR(layout->pcs)) + return PTR_ERR(layout->pcs); - qmp->tx2 = devm_of_iomap(dev, np, 3, NULL); - if (IS_ERR(qmp->tx2)) - return PTR_ERR(qmp->tx2); + layout->tx2 = devm_of_iomap(dev, np, 3, NULL); + if (IS_ERR(layout->tx2)) + return PTR_ERR(layout->tx2); - qmp->rx2 = devm_of_iomap(dev, np, 4, NULL); - if (IS_ERR(qmp->rx2)) - return PTR_ERR(qmp->rx2); + layout->rx2 = devm_of_iomap(dev, np, 4, NULL); + if (IS_ERR(layout->rx2)) + return PTR_ERR(layout->rx2); - qmp->pcs_misc = devm_of_iomap(dev, np, 5, NULL); - if (IS_ERR(qmp->pcs_misc)) { + layout->pcs_misc = devm_of_iomap(dev, np, 5, NULL); + if (IS_ERR(layout->pcs_misc)) { dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); - qmp->pcs_misc = NULL; + layout->pcs_misc = NULL; } - qmp->pipe_clk = devm_get_clk_from_child(dev, np, NULL); - if (IS_ERR(qmp->pipe_clk)) { - return dev_err_probe(dev, PTR_ERR(qmp->pipe_clk), + layout->pipe_clk = devm_get_clk_from_child(dev, np, NULL); + if (IS_ERR(layout->pipe_clk)) { + return dev_err_probe(dev, PTR_ERR(layout->pipe_clk), "failed to get pipe clock\n"); } @@ -969,11 +1693,12 @@ static int qmp_usbc_parse_dt_legacy(struct qmp_usbc *qmp, struct device_node *np return 0; } -static int qmp_usbc_parse_dt(struct qmp_usbc *qmp) +static int qmp_usbc_parse_usb_dt(struct qmp_usbc *qmp) { struct platform_device *pdev = to_platform_device(qmp->dev); - const struct qmp_phy_cfg *cfg = qmp->cfg; - const struct qmp_usbc_offsets *offs = cfg->offsets; + const struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp); + const struct qmp_usbc_usb_offsets *offs = cfg->offsets; + struct qmp_phy_usb_layout *layout = to_usb_layout(qmp); struct device *dev = qmp->dev; void __iomem *base; int ret; @@ -985,23 +1710,23 @@ static int qmp_usbc_parse_dt(struct qmp_usbc *qmp) if (IS_ERR(base)) return PTR_ERR(base); - qmp->serdes = base + offs->serdes; - qmp->pcs = base + offs->pcs; + layout->serdes = base + offs->serdes; + layout->pcs = base + offs->pcs; if (offs->pcs_misc) - qmp->pcs_misc = base + offs->pcs_misc; - qmp->tx = base + offs->tx; - qmp->rx = base + offs->rx; + layout->pcs_misc = base + offs->pcs_misc; + layout->tx = base + offs->tx; + layout->rx = base + offs->rx; - qmp->tx2 = base + offs->tx2; - qmp->rx2 = base + offs->rx2; + layout->tx2 = base + offs->tx2; + layout->rx2 = base + offs->rx2; ret = qmp_usbc_clk_init(qmp); if (ret) return ret; - qmp->pipe_clk = devm_clk_get(dev, "pipe"); - if (IS_ERR(qmp->pipe_clk)) { - return dev_err_probe(dev, PTR_ERR(qmp->pipe_clk), + layout->pipe_clk = devm_clk_get(dev, "pipe"); + if (IS_ERR(layout->pipe_clk)) { + return dev_err_probe(dev, PTR_ERR(layout->pipe_clk), "failed to get pipe clock\n"); } @@ -1013,10 +1738,11 @@ static int qmp_usbc_parse_dt(struct qmp_usbc *qmp) return 0; } -static int qmp_usbc_parse_vls_clamp(struct qmp_usbc *qmp) +static int qmp_usbc_parse_usb_vls_clamp(struct qmp_usbc *qmp) { struct of_phandle_args tcsr_args; struct device *dev = qmp->dev; + struct qmp_phy_usb_layout *layout = to_usb_layout(qmp); int ret; /* for backwards compatibility ignore if there is no property */ @@ -1027,22 +1753,280 @@ static int qmp_usbc_parse_vls_clamp(struct qmp_usbc *qmp) else if (ret < 0) return dev_err_probe(dev, ret, "Failed to parse qcom,tcsr-reg\n"); - qmp->tcsr_map = syscon_node_to_regmap(tcsr_args.np); + layout->tcsr_map = syscon_node_to_regmap(tcsr_args.np); of_node_put(tcsr_args.np); - if (IS_ERR(qmp->tcsr_map)) - return PTR_ERR(qmp->tcsr_map); + if (IS_ERR(layout->tcsr_map)) + return PTR_ERR(layout->tcsr_map); - qmp->vls_clamp_reg = tcsr_args.args[0]; + layout->vls_clamp_reg = tcsr_args.args[0]; return 0; } +static int qmp_usbc_parse_dp_phy_mode(struct qmp_usbc *qmp) +{ + struct of_phandle_args tcsr_args; + struct device *dev = qmp->dev; + struct qmp_phy_dp_layout *layout = to_dp_layout(qmp); + int ret; + + /* for backwards compatibility ignore if there is no property */ + ret = of_parse_phandle_with_fixed_args(dev->of_node, "qcom,tcsr-reg", 1, 0, + &tcsr_args); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to parse qcom,tcsr-reg\n"); + + layout->tcsr_map = syscon_node_to_regmap(tcsr_args.np); + of_node_put(tcsr_args.np); + if (IS_ERR(layout->tcsr_map)) + return PTR_ERR(layout->tcsr_map); + + layout->dp_phy_mode = tcsr_args.args[0]; + + return 0; +} + +static int qmp_usbc_parse_dp_dt(struct qmp_usbc *qmp) +{ + struct platform_device *pdev = to_platform_device(qmp->dev); + struct qmp_phy_dp_layout *layout = to_dp_layout(qmp); + struct qmp_phy_dp_cfg *cfg = to_dp_cfg(qmp); + const struct qmp_usbc_dp_offsets *offs = cfg->offsets; + struct device *dev = qmp->dev; + void __iomem *base; + int ret; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) { + dev_err(dev, "get resource fail, ret:%d\n", ret); + return PTR_ERR(base); + } + + layout->dp_serdes = base + offs->dp_serdes; + layout->dp_tx = base + offs->dp_txa; + layout->dp_tx2 = base + offs->dp_txb; + layout->dp_phy = base + offs->dp_phy; + + ret = qmp_usbc_clk_init(qmp); + if (ret) { + dev_err(dev, "clk init fail, ret:%d\n", ret); + return ret; + } + + ret = qmp_usbc_reset_init(qmp, dp_usb3phy_reset_l, + ARRAY_SIZE(dp_usb3phy_reset_l)); + if (ret) + return ret; + + return 0; +} + +/* + * Display Port PLL driver block diagram for branch clocks + * + * +------------------------------+ + * | DP_VCO_CLK | + * | | + * | +-------------------+ | + * | | (DP PLL/VCO) | | + * | +---------+---------+ | + * | v | + * | +----------+-----------+ | + * | | hsclk_divsel_clk_src | | + * | +----------+-----------+ | + * +------------------------------+ + * | + * +---------<---------v------------>----------+ + * | | + * +--------v----------------+ | + * | dp_phy_pll_link_clk | | + * | link_clk | | + * +--------+----------------+ | + * | | + * | | + * v v + * Input to DISPCC block | + * for link clk, crypto clk | + * and interface clock | + * | + * | + * +--------<------------+-----------------+---<---+ + * | | | + * +----v---------+ +--------v-----+ +--------v------+ + * | vco_divided | | vco_divided | | vco_divided | + * | _clk_src | | _clk_src | | _clk_src | + * | | | | | | + * |divsel_six | | divsel_two | | divsel_four | + * +-------+------+ +-----+--------+ +--------+------+ + * | | | + * v---->----------v-------------<------v + * | + * +----------+-----------------+ + * | dp_phy_pll_vco_div_clk | + * +---------+------------------+ + * | + * v + * Input to DISPCC block + * for DP pixel clock + * + */ +static int qmp_dp_pixel_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) +{ + switch (req->rate) { + case 1620000000UL / 2: + case 2700000000UL / 2: + /* 5.4 and 8.1 GHz are same link rate as 2.7GHz, i.e. div 4 and div 6 */ + return 0; + default: + return -EINVAL; + } +} + +static unsigned long qmp_dp_pixel_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + // const struct qmp_usbc *qmp; + struct qmp_phy_dp_layout *layout; + const struct phy_configure_opts_dp *dp_opts; + + layout = container_of(hw, struct qmp_phy_dp_layout, dp_pixel_hw); + + dp_opts = &layout->dp_opts; + + switch (dp_opts->link_rate) { + case 1620: + return 1620000000UL / 2; + case 2700: + return 2700000000UL / 2; + case 5400: + return 5400000000UL / 4; + case 8100: + return 8100000000UL / 6; + default: + return 0; + } +} + +static const struct clk_ops qmp_dp_pixel_clk_ops = { + .determine_rate = qmp_dp_pixel_clk_determine_rate, + .recalc_rate = qmp_dp_pixel_clk_recalc_rate, +}; + +static int qmp_dp_link_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) +{ + switch (req->rate) { + case 162000000: + case 270000000: + case 540000000: + case 810000000: + return 0; + default: + return -EINVAL; + } +} + +static unsigned long qmp_dp_link_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + // const struct qmp_combo *qmp; + struct qmp_phy_dp_layout *layout; + const struct phy_configure_opts_dp *dp_opts; + + layout = container_of(hw, struct qmp_phy_dp_layout, dp_link_hw); + dp_opts = &layout->dp_opts; + + switch (dp_opts->link_rate) { + case 1620: + case 2700: + case 5400: + case 8100: + return dp_opts->link_rate * 100000; + default: + return 0; + } +} + +static const struct clk_ops qmp_dp_link_clk_ops = { + .determine_rate = qmp_dp_link_clk_determine_rate, + .recalc_rate = qmp_dp_link_clk_recalc_rate, +}; + +static int phy_dp_clks_register(struct qmp_usbc *qmp, struct device_node *np) +{ + struct clk_init_data init = { }; + int ret = 0; + struct qmp_phy_dp_layout *layout = to_dp_layout(qmp); + + ret = of_property_read_string_index(np, "clock-output-names", 0, &init.name); + if (ret < 0) { + dev_err(qmp->dev, "%pOFn: No link clock-output-names\n", np); + return ret; + } + + init.ops = &qmp_dp_link_clk_ops; + layout->dp_link_hw.init = &init; + ret = devm_clk_hw_register(qmp->dev, &layout->dp_link_hw); + if (ret < 0) { + dev_err(qmp->dev, "link clk reg fail ret=%d\n", ret); + return ret; + } + + ret = of_property_read_string_index(np, "clock-output-names", 1, &init.name); + if (ret) { + dev_err(qmp->dev, "%pOFn: No div clock-output-names\n", np); + return ret; + } + + init.ops = &qmp_dp_pixel_clk_ops; + layout->dp_pixel_hw.init = &init; + ret = devm_clk_hw_register(qmp->dev, &layout->dp_pixel_hw); + if (ret) { + dev_err(qmp->dev, "pxl clk reg fail ret=%d\n", ret); + return ret; + } + + return 0; +} + +static struct clk_hw *qmp_dp_clks_hw_get(struct of_phandle_args *clkspec, void *data) +{ + struct qmp_usbc *qmp = data; + struct qmp_phy_dp_layout *layout = to_dp_layout(qmp); + + switch (clkspec->args[0]) { + case QMP_USB43DP_DP_LINK_CLK: + return &layout->dp_link_hw; + case QMP_USB43DP_DP_VCO_DIV_CLK: + return &layout->dp_pixel_hw; + } + + return ERR_PTR(-EINVAL); +} + +static int qmp_dp_register_clocks(struct qmp_usbc *qmp, struct device_node *dp_np) +{ + int ret; + + ret = phy_dp_clks_register(qmp, dp_np); + if (ret) { + dev_err(qmp->dev, "dp clk reg fail ret:%d\n", ret); + return ret; + } + + ret = of_clk_add_hw_provider(dp_np, qmp_dp_clks_hw_get, qmp); + if (ret) { + dev_err(qmp->dev, "add provider fail ret:%d\n", ret); + return ret; + } + + return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, dp_np); +} + static int qmp_usbc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct phy_provider *phy_provider; struct device_node *np; struct qmp_usbc *qmp; + const struct dev_cfg *data_cfg; int ret; qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL); @@ -1050,38 +2034,74 @@ static int qmp_usbc_probe(struct platform_device *pdev) return -ENOMEM; qmp->dev = dev; - dev_set_drvdata(dev, qmp); qmp->orientation = TYPEC_ORIENTATION_NORMAL; - qmp->cfg = of_device_get_match_data(dev); - if (!qmp->cfg) + qmp->init_count = 0; + + data_cfg = of_device_get_match_data(dev); + if (!data_cfg) { + dev_err(qmp->dev, "get data fail\n"); return -EINVAL; + } mutex_init(&qmp->phy_mutex); - ret = qmp_usbc_vreg_init(qmp); - if (ret) - return ret; + qmp->type = data_cfg->type; + qmp->cfg = data_cfg->cfg; - ret = qmp_usbc_typec_switch_register(qmp); - if (ret) + ret = qmp_usbc_vreg_init(qmp); + if (ret) { + dev_err(qmp->dev, "qmp_type(%d) vreg init fail\n", qmp->type); return ret; + } - ret = qmp_usbc_parse_vls_clamp(qmp); - if (ret) - return ret; + if (qmp->type == QMP_PHY_USBC_USB) { + qmp->layout = devm_kzalloc(dev, sizeof(struct qmp_phy_usb_layout), GFP_KERNEL); + if (!qmp->layout) + return -ENOMEM; + + ret = qmp_usbc_typec_switch_register(qmp); + if (ret) + return ret; + + ret = qmp_usbc_parse_usb_vls_clamp(qmp); + if (ret) + return ret; + + /* Check for legacy binding with child node. */ + np = of_get_child_by_name(dev->of_node, "phy"); + if (np) { + ret = qmp_usbc_parse_usb_dt_legacy(qmp, np); + } else { + np = of_node_get(dev->of_node); + ret = qmp_usbc_parse_usb_dt(qmp); + } + if (ret) + goto err_node_put; + } else if (qmp->type == QMP_PHY_USBC_DP) { + qmp->layout = devm_kzalloc(dev, sizeof(struct qmp_phy_dp_layout), GFP_KERNEL); + if (!qmp->layout) + return -ENOMEM; - /* Check for legacy binding with child node. */ - np = of_get_child_by_name(dev->of_node, "phy"); - if (np) { - ret = qmp_usbc_parse_dt_legacy(qmp, np); - } else { np = of_node_get(dev->of_node); - ret = qmp_usbc_parse_dt(qmp); - } - if (ret) + ret = qmp_usbc_parse_dp_phy_mode(qmp); + if (ret) + goto err_node_put; + + ret = qmp_usbc_parse_dp_dt(qmp); + if (ret) + goto err_node_put; + + ret = drm_aux_bridge_register(dev); + if (ret) { + dev_err(qmp->dev, "aux bridge reg fail ret=%d\n", ret); + goto err_node_put; + } + } else { + dev_err(dev, "invalid phy type: %d\n", qmp->type); goto err_node_put; + } pm_runtime_set_active(dev); ret = devm_pm_runtime_enable(dev); @@ -1093,19 +2113,33 @@ static int qmp_usbc_probe(struct platform_device *pdev) */ pm_runtime_forbid(dev); - ret = phy_pipe_clk_register(qmp, np); - if (ret) - goto err_node_put; - - qmp->phy = devm_phy_create(dev, np, &qmp_usbc_phy_ops); - if (IS_ERR(qmp->phy)) { - ret = PTR_ERR(qmp->phy); - dev_err(dev, "failed to create PHY: %d\n", ret); - goto err_node_put; + if (qmp->type == QMP_PHY_USBC_USB) { + // pipe clk process + ret = phy_pipe_clk_register(qmp, np); + if (ret) + goto err_node_put; + + qmp->phy = devm_phy_create(dev, np, &qmp_usbc_usb_phy_ops); + if (IS_ERR(qmp->phy)) { + ret = PTR_ERR(qmp->phy); + dev_err(dev, "failed to create PHY: %d\n", ret); + goto err_node_put; + } + } else { + ret = qmp_dp_register_clocks(qmp, np); + if (ret) + goto err_node_put; + + qmp->phy = devm_phy_create(dev, np, &qmp_usbc_dp_phy_ops); + if (IS_ERR(qmp->phy)) { + ret = PTR_ERR(qmp->phy); + dev_err(dev, "failed to create PHY: %d\n", ret); + goto err_node_put; + } } phy_set_drvdata(qmp->phy, qmp); - + dev_set_drvdata(dev, qmp); of_node_put(np); phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); @@ -1120,19 +2154,38 @@ static int qmp_usbc_probe(struct platform_device *pdev) static const struct of_device_id qmp_usbc_of_match_table[] = { { .compatible = "qcom,msm8998-qmp-usb3-phy", - .data = &msm8998_usb3phy_cfg, + .data = &(struct dev_cfg) { + .type = QMP_PHY_USBC_USB, + .cfg = &msm8998_usb3phy_cfg, + }, }, { .compatible = "qcom,qcm2290-qmp-usb3-phy", - .data = &qcm2290_usb3phy_cfg, + .data = &(struct dev_cfg) { + .type = QMP_PHY_USBC_USB, + .cfg = &qcm2290_usb3phy_cfg, + }, + }, { + .compatible = "qcom,qcs615-qmp-dp-phy", + .data = &(struct dev_cfg) { + .type = QMP_PHY_USBC_DP, + .cfg = &qcs615_dpphy_cfg, + }, }, { .compatible = "qcom,sdm660-qmp-usb3-phy", - .data = &sdm660_usb3phy_cfg, + .data = &(struct dev_cfg) { + .type = QMP_PHY_USBC_USB, + .cfg = &sdm660_usb3phy_cfg, + }, }, { .compatible = "qcom,sm6115-qmp-usb3-phy", - .data = &qcm2290_usb3phy_cfg, + .data = &(struct dev_cfg) { + .type = QMP_PHY_USBC_USB, + .cfg = &qcm2290_usb3phy_cfg, + }, }, { }, }; + MODULE_DEVICE_TABLE(of, qmp_usbc_of_match_table); static struct platform_driver qmp_usbc_driver = { From patchwork Fri Nov 29 07:57:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiangxu Yin X-Patchwork-Id: 13888466 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 106F6D6EBE5 for ; Fri, 29 Nov 2024 07:59:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:CC:To:In-Reply-To:References:Message-ID :MIME-Version:Subject:Date:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=HFemTAnJVFqkqJl6xxg7nUsJWHtQK8QJlGB4vQEHyiI=; b=rlQDFAOILRs0HQ EB9/ofFJkH9Wcy0V6Ca/IsnXsujaA7PhMCwPwEZMqhbMMYbhTOr3Vtx4gDDU2oQ6iJ4H3PJgKx9Qh lBXNHhaVdFnJ9aJY3Chft8vjmzMAz4usz4PI3D6TuxfTbcL+w6DU2Aq2H+kH26ftYV+YacTxTjaHz reg+ktfnCrhi17xcf0pwfKfsU+E5F7W6wBGZOEGQ6qR7B1/WzJB39igLyf+NZJCBKBfu246IhXDnM P+tk/J5FYfUnyk86mgH0/c9n3kJZ538UIDM8Hy9ECp+FdBPB5lWn1d3ffLpswfTThwgG566l5S4w8 aHa4vkT4KE3ue8xkXZ5Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tGvuD-0000000H7Ho-3QQM; Fri, 29 Nov 2024 07:59:13 +0000 Received: from mx0a-0031df01.pphosted.com ([205.220.168.131]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tGvuC-0000000H7H3-1uiR for linux-phy@lists.infradead.org; Fri, 29 Nov 2024 07:59:13 +0000 Received: from pps.filterd (m0279867.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4ASLZ0H7016159; Fri, 29 Nov 2024 07:59:06 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= XVCkS1n5isUkD6St2U5ImlwEPDM5/G/PceH/hFE9t0E=; b=O4Sf3aRBLkkE6Uq/ 89kGsZbrJcY7rg3UuxYoEfsqFkhqva+vi1Fs2vzsnjKyOJ7eci8sT6rCXDAKtwji GAXhz7H4zLPPzpzbpewtuiHwn2dOUsAJjlUZyrOo00z+UoMmdtjPt4nRErZAOoDc S50eu6f0wkHL2IN9PxS0vxDoxfkm3qEwWBFYOaXw5AaKQBDOZQ475n+GgDqDe6bE owgSeb2OzajfdbfDDA7rnIqHbwASL6axeAfN/HtnAZHrsjhMZVXsldDCiZ/VSBBA 1Wh9P376ipUcQNhLHZftXCSnqtl6PQ6PHZ9A2UahA4JDDkjEwyxBuCssSqdgKn/w 0nOknA== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4366xw4uhp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:59:06 +0000 (GMT) Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AT7x5NQ002192 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:59:05 GMT Received: from szioemm-lnxbld002.qualcomm.com (10.80.80.8) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 28 Nov 2024 23:58:57 -0800 From: Xiangxu Yin Date: Fri, 29 Nov 2024 15:57:44 +0800 Subject: [PATCH 4/8] drm/msm/dp: Add DisplayPort support for QCS615 MIME-Version: 1.0 Message-ID: <20241129-add-displayport-support-for-qcs615-platform-v1-4-09a4338d93ef@quicinc.com> References: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> In-Reply-To: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> To: Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Kuogee Hsieh , Vinod Koul , Kishon Vijay Abraham I , Linus Walleij , Bartosz Golaszewski , , CC: , , , , , , , Xiangxu Yin X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732867103; l=1131; i=quic_xiangxuy@quicinc.com; s=20241125; h=from:subject:message-id; bh=5x0yri9P1gEuZjvUczF/frYZpbWKZ4iO+JmsEFbc160=; b=lyPLf9FBAUHwx2XWkgg66YkT0Dvh1D6x5zd8EBm8Bd/J9VLg+j5Z9Y/1OypGIVzkdsaTAFj7V of0ZQvagDmODTOME9kWHn7wceksIMsmYucxp8Gsovf4npoLIy+Evbj8 X-Developer-Key: i=quic_xiangxuy@quicinc.com; a=ed25519; pk=F1TwipJzpywfbt3n/RPi4l/A4AVF+QC89XzCHgZYaOc= X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: yB73dpLac40WBAysreEBNdb_T9vbyyvT X-Proofpoint-ORIG-GUID: yB73dpLac40WBAysreEBNdb_T9vbyyvT X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 malwarescore=0 bulkscore=0 impostorscore=0 priorityscore=1501 clxscore=1011 mlxlogscore=999 phishscore=0 adultscore=0 spamscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2411290064 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241128_235912_504245_95483484 X-CRM114-Status: GOOD ( 11.76 ) X-BeenThere: linux-phy@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux Phy Mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-phy" Errors-To: linux-phy-bounces+linux-phy=archiver.kernel.org@lists.infradead.org The Qualcomm QCS615 platform comes with a DisplayPort controller use the same base offset as sc7180. add support for this in DP driver. Signed-off-by: Xiangxu Yin Reviewed-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_display.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index aba925aab7ad7c6652e81004043864c1cb3ac370..4c83402fc7e0d41cb7621fa2efda043269d0a608 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -179,6 +179,7 @@ static const struct of_device_id msm_dp_dt_match[] = { { .compatible = "qcom,sc8280xp-dp", .data = &msm_dp_desc_sc8280xp }, { .compatible = "qcom,sc8280xp-edp", .data = &msm_dp_desc_sc8280xp }, { .compatible = "qcom,sdm845-dp", .data = &msm_dp_desc_sc7180 }, + { .compatible = "qcom,sm6150-dp", .data = &msm_dp_desc_sc7180 }, { .compatible = "qcom,sm8350-dp", .data = &msm_dp_desc_sc7180 }, { .compatible = "qcom,sm8650-dp", .data = &msm_dp_desc_sm8650 }, { .compatible = "qcom,x1e80100-dp", .data = &msm_dp_desc_x1e80100 }, From patchwork Fri Nov 29 07:57:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiangxu Yin X-Patchwork-Id: 13888468 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 530BFD6EBE2 for ; Fri, 29 Nov 2024 07:59:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:CC:To:In-Reply-To:References:Message-ID :MIME-Version:Subject:Date:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=gnEsM+T6e0q6iINPmivHrR7IzZseHLDmHHv1+c+1pg0=; b=On8awkvi+eU2eu 6A0h1EM5gjrtEFDsn+NwNfV8DAybvIsPxbkLJN69m5oLZnfkizknXW97Kdg0hzWmZTCPqaNmp2b/k ZxiHkjYRyiHB0AqCOFFSC2grTFURAM8sLUo+DtHPgiWjODnNoklAjZekosgTu8vUdEoPs6g3tuaHG N3PRWxcd2cCBuHIX4x2+bDvmTNAn1gsnh7GnZ8NCBPBC6k4c9eu1KQVbxZ9yOO/VrsblgP3Sz8Tdi Sqqhe3xBv1O4mE2byppyS6gymkmyStuKyjqPPRVfKMgxoi646/euknYsa+JGU1/ArtbAHCltbToG8 tJbA/svv1wnTlMMxYeYg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tGvuS-0000000H7La-0PGC; Fri, 29 Nov 2024 07:59:28 +0000 Received: from mx0b-0031df01.pphosted.com ([205.220.180.131]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tGvuP-0000000H7Km-3bdd for linux-phy@lists.infradead.org; Fri, 29 Nov 2024 07:59:27 +0000 Received: from pps.filterd (m0279871.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4ASLaNnN005340; Fri, 29 Nov 2024 07:59:16 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= 5vazB+Ionp0PSKd7IWWqKrZgvudBsapwrpYb6Ty25p4=; b=fWsfyuDAS07nce20 0SrMqezYTx7LsDqZPbK6+5h4vrnbjc709z6tqcYPPcRsTZJA09iLCzayFVV+EdTh 5Cyee58Jcn3pWb+old6GhlQNhF87BNihg219b5P7zHNVmsyCkpQg+zGirVKJqPU6 2sOrHZEk7C4G0nc++3JQ25xwVB0bMzJRrs7yULYSFQOixeoWR8pR8+1TTbDOHJpV Chy/868oRy26Q1CzqgECjSdMzN19CjhsAuETY45H9npTVXFlRCRrygjPh/sd1VFv vvCobPAAGzP/XLTskENcbhCbEabIJeGf0m2rvwpbxmOmEzVUwwVWeocOanM/LTWc k1K7wQ== Received: from nasanppmta02.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 436h2mkh38-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:59:16 +0000 (GMT) Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA02.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AT7xEao008543 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:59:15 GMT Received: from szioemm-lnxbld002.qualcomm.com (10.80.80.8) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 28 Nov 2024 23:59:06 -0800 From: Xiangxu Yin Date: Fri, 29 Nov 2024 15:57:45 +0800 Subject: [PATCH 5/8] drm/msm/dp: Add support for lane mapping configuration MIME-Version: 1.0 Message-ID: <20241129-add-displayport-support-for-qcs615-platform-v1-5-09a4338d93ef@quicinc.com> References: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> In-Reply-To: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> To: Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Kuogee Hsieh , Vinod Koul , Kishon Vijay Abraham I , Linus Walleij , Bartosz Golaszewski , , CC: , , , , , , , Xiangxu Yin X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732867104; l=5838; i=quic_xiangxuy@quicinc.com; s=20241125; h=from:subject:message-id; bh=/IgyM/liAriauN4eF/1R+rpbTJIiazRez7scLYygZYw=; b=wUyFz4XSuL1HBC5BRc0E3JmDFI+Z10ugIrepp52Bfxzy2+VTam2Pfq++pf7oYMtxzuBphH6pY 4nDVuhikwQqBUS9nu3SNxn/ZF3I+LUuW1UpwMt7tZr/pJRBHaPtQb3T X-Developer-Key: i=quic_xiangxuy@quicinc.com; a=ed25519; pk=F1TwipJzpywfbt3n/RPi4l/A4AVF+QC89XzCHgZYaOc= X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: Lu6ie7qPRZkLez5-hjh4ZyU5sMt2psKG X-Proofpoint-ORIG-GUID: Lu6ie7qPRZkLez5-hjh4ZyU5sMt2psKG X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 bulkscore=0 malwarescore=0 phishscore=0 suspectscore=0 adultscore=0 spamscore=0 lowpriorityscore=0 mlxscore=0 impostorscore=0 clxscore=1011 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2411290064 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241128_235926_026273_D6F1C689 X-CRM114-Status: GOOD ( 19.38 ) X-BeenThere: linux-phy@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux Phy Mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-phy" Errors-To: linux-phy-bounces+linux-phy=archiver.kernel.org@lists.infradead.org Add the ability to configure lane mapping for the DP controller. This is required when the platform's lane mapping does not follow the default order (0, 1, 2, 3). The mapping rules are now configurable via the `data-lane` property in the devicetree. This property defines the logical-to-physical lane mapping sequence, ensuring correct lane assignment for non-default configurations. Signed-off-by: Xiangxu Yin --- drivers/gpu/drm/msm/dp/dp_catalog.c | 11 +++++------ drivers/gpu/drm/msm/dp/dp_catalog.h | 2 +- drivers/gpu/drm/msm/dp/dp_ctrl.c | 2 +- drivers/gpu/drm/msm/dp/dp_panel.c | 13 ++++++++++--- drivers/gpu/drm/msm/dp/dp_panel.h | 3 +++ 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index b4c8856fb25d01dd1b30c5ec33ce821aafa9551d..34439d0709d2e1437e5669fd0b995936420ee16f 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -361,17 +361,16 @@ void msm_dp_catalog_ctrl_config_ctrl(struct msm_dp_catalog *msm_dp_catalog, u32 msm_dp_write_link(catalog, REG_DP_CONFIGURATION_CTRL, cfg); } -void msm_dp_catalog_ctrl_lane_mapping(struct msm_dp_catalog *msm_dp_catalog) +void msm_dp_catalog_ctrl_lane_mapping(struct msm_dp_catalog *msm_dp_catalog, u32 *l_map) { struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog, struct msm_dp_catalog_private, msm_dp_catalog); - u32 ln_0 = 0, ln_1 = 1, ln_2 = 2, ln_3 = 3; /* One-to-One mapping */ u32 ln_mapping; - ln_mapping = ln_0 << LANE0_MAPPING_SHIFT; - ln_mapping |= ln_1 << LANE1_MAPPING_SHIFT; - ln_mapping |= ln_2 << LANE2_MAPPING_SHIFT; - ln_mapping |= ln_3 << LANE3_MAPPING_SHIFT; + ln_mapping = l_map[0] << LANE0_MAPPING_SHIFT; + ln_mapping |= l_map[1] << LANE1_MAPPING_SHIFT; + ln_mapping |= l_map[2] << LANE2_MAPPING_SHIFT; + ln_mapping |= l_map[3] << LANE3_MAPPING_SHIFT; msm_dp_write_link(catalog, REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING, ln_mapping); diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index e932b17eecbf514070cd8cd0b98ca0fefbe81ab7..8b8de2a7d3ad561c1901e1bdaad92d4fab12e808 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -69,7 +69,7 @@ u32 msm_dp_catalog_aux_get_irq(struct msm_dp_catalog *msm_dp_catalog); /* DP Controller APIs */ void msm_dp_catalog_ctrl_state_ctrl(struct msm_dp_catalog *msm_dp_catalog, u32 state); void msm_dp_catalog_ctrl_config_ctrl(struct msm_dp_catalog *msm_dp_catalog, u32 config); -void msm_dp_catalog_ctrl_lane_mapping(struct msm_dp_catalog *msm_dp_catalog); +void msm_dp_catalog_ctrl_lane_mapping(struct msm_dp_catalog *msm_dp_catalog, u32 *l_map); void msm_dp_catalog_ctrl_mainlink_ctrl(struct msm_dp_catalog *msm_dp_catalog, bool enable); void msm_dp_catalog_ctrl_psr_mainlink_enable(struct msm_dp_catalog *msm_dp_catalog, bool enable); void msm_dp_catalog_setup_peripheral_flush(struct msm_dp_catalog *msm_dp_catalog); diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index bc2ca8133b790fc049e18ab3b37a629558664dd4..49c8ce9b2d0e57a613e50865be3fe98e814d425a 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -177,7 +177,7 @@ static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl { u32 cc, tb; - msm_dp_catalog_ctrl_lane_mapping(ctrl->catalog); + msm_dp_catalog_ctrl_lane_mapping(ctrl->catalog, ctrl->panel->lane_map); msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true); msm_dp_catalog_setup_peripheral_flush(ctrl->catalog); diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 5d7eaa31bf3176566f40f01ff636bee64e81c64f..8654180aa259234bbd41f4f88c13c485f9791b1d 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -11,7 +11,6 @@ #include #include -#define DP_MAX_NUM_DP_LANES 4 #define DP_LINK_RATE_HBR2 540000 /* kbytes */ struct msm_dp_panel_private { @@ -461,6 +460,7 @@ static int msm_dp_panel_parse_dt(struct msm_dp_panel *msm_dp_panel) struct msm_dp_panel_private *panel; struct device_node *of_node; int cnt; + u32 lane_map[DP_MAX_NUM_DP_LANES] = {0, 1, 2, 3}; panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); of_node = panel->dev->of_node; @@ -474,10 +474,17 @@ static int msm_dp_panel_parse_dt(struct msm_dp_panel *msm_dp_panel) cnt = drm_of_get_data_lanes_count(of_node, 1, DP_MAX_NUM_DP_LANES); } - if (cnt > 0) + if (cnt > 0) { + struct device_node *endpoint; + msm_dp_panel->max_dp_lanes = cnt; - else + endpoint = of_graph_get_endpoint_by_regs(of_node, 1, -1); + of_property_read_u32_array(endpoint, "data-lanes", lane_map, cnt); + } else { msm_dp_panel->max_dp_lanes = DP_MAX_NUM_DP_LANES; /* 4 lanes */ + } + + memcpy(msm_dp_panel->lane_map, lane_map, msm_dp_panel->max_dp_lanes * sizeof(u32)); msm_dp_panel->max_dp_link_rate = msm_dp_panel_link_frequencies(of_node); if (!msm_dp_panel->max_dp_link_rate) diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 0e944db3adf2f187f313664fe80cf540ec7a19f2..7603b92c32902bd3d4485539bd6308537ff75a2c 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -11,6 +11,8 @@ #include "dp_aux.h" #include "dp_link.h" +#define DP_MAX_NUM_DP_LANES 4 + struct edid; struct msm_dp_display_mode { @@ -46,6 +48,7 @@ struct msm_dp_panel { bool video_test; bool vsc_sdp_supported; + u32 lane_map[DP_MAX_NUM_DP_LANES]; u32 max_dp_lanes; u32 max_dp_link_rate; From patchwork Fri Nov 29 07:57:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiangxu Yin X-Patchwork-Id: 13888469 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A2AF0D6EBE2 for ; Fri, 29 Nov 2024 07:59:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:CC:To:In-Reply-To:References:Message-ID :MIME-Version:Subject:Date:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=15IuTcYwGXq5tb+pZhCMccGs3vTqQdm6zDv15cCHWJI=; b=Oq96uocqmsrzyq R/KAOOiTq9mW9aGudx7WPwHQ+0Eqneh0rHQQGgczevgIktGDu9xgqi/ZGDqpwZoc01ULsQ0NdRCPU 0MwYvRsl9WUVlwS/jMrK9s/GzSQg2Ryb4TWFKBlvPWURK+XMbap2Ichmg/Ph9oc0jdv4/KBKdWQcl ODMTpsVqfZFi3Ukm3VyFf9f6G4u1Q+YvaYZl9SHLbraLZU99NL6mFNXp3xfzLZNv7/k3qmfZW/j9u kcqipMRAYRvVQkA3w2Mqj1mZw6SyNeeA8pDjBmdlx57jfyzZqMGUC8gsbRQ3JcwJ3CcgDZcqOlc7y HA7b8S5dMFbNxpFeI4XQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tGvuW-0000000H7NE-1ZT2; Fri, 29 Nov 2024 07:59:32 +0000 Received: from mx0a-0031df01.pphosted.com ([205.220.168.131]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tGvuU-0000000H7M2-0kNV for linux-phy@lists.infradead.org; Fri, 29 Nov 2024 07:59:31 +0000 Received: from pps.filterd (m0279865.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AT7kb44021829; Fri, 29 Nov 2024 07:59:24 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= TbFElqNPhwIjgusYstPdi/mfDQMF/VQe9i3wtdDMMJ4=; b=FUH0/8mWXRqskF/U c20BYQwKlRiFDjtvGS7O6dgT6ojvXzd9Wg04nOni7LIOfPzzKEVeG5m2I4+uxoFC i4VyIcZGg2gVuQbBhHbHrW7mrwe0rdLYGP6SJonphvEeSvU+fJ6gmmY4sRU5Bsa8 dPRVShOBbLzSOSpOe6Yl10HhqLYszX7PRgrLnBB4iEsz/6r22IN2RnntyzxuGhrj lEQ15CVoWMNvydhyNX88wJq811vB1cy8gCi/gyE4virCySltLEwKVY3f/Bduh8Ve EaVbIXfg6N/JHhUrJ+Ra0s3EdDIaenj9mmH/vkRMo5m8XbQGFZvEUuV2w53jBLsk U2vUbQ== Received: from nasanppmta03.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4379h680ub-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:59:23 +0000 (GMT) Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA03.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AT7xNxJ030756 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:59:23 GMT Received: from szioemm-lnxbld002.qualcomm.com (10.80.80.8) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 28 Nov 2024 23:59:15 -0800 From: Xiangxu Yin Date: Fri, 29 Nov 2024 15:57:46 +0800 Subject: [PATCH 6/8] drm/msm/dp: Add maximum width limitation for modes MIME-Version: 1.0 Message-ID: <20241129-add-displayport-support-for-qcs615-platform-v1-6-09a4338d93ef@quicinc.com> References: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> In-Reply-To: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> To: Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Kuogee Hsieh , Vinod Koul , Kishon Vijay Abraham I , Linus Walleij , Bartosz Golaszewski , , CC: , , , , , , , Xiangxu Yin X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732867104; l=3265; i=quic_xiangxuy@quicinc.com; s=20241125; h=from:subject:message-id; bh=DbkEW7dSUNNaGIQMV5aGvjb+lO1ylplI6eCfwM9os9s=; b=IuT1G4L5LXDkuuCsNfiXfFmVT9EqanDRhFrTr+/pRef7XoWDDo65u1sCWLAX8mr5yhZwAvzRa iPow7dAopf3Dij7r6LrnqiEQtW8Ts/xsW/3+a/Cfi4/YGvP7gTZ6ekt X-Developer-Key: i=quic_xiangxuy@quicinc.com; a=ed25519; pk=F1TwipJzpywfbt3n/RPi4l/A4AVF+QC89XzCHgZYaOc= X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: tXBegRoUrXuzxO5kusLoerYuLVkFxDS3 X-Proofpoint-ORIG-GUID: tXBegRoUrXuzxO5kusLoerYuLVkFxDS3 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 malwarescore=0 mlxlogscore=999 mlxscore=0 suspectscore=0 priorityscore=1501 lowpriorityscore=0 bulkscore=0 phishscore=0 adultscore=0 spamscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2411290064 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241128_235930_239130_20748D32 X-CRM114-Status: GOOD ( 15.33 ) X-BeenThere: linux-phy@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux Phy Mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-phy" Errors-To: linux-phy-bounces+linux-phy=archiver.kernel.org@lists.infradead.org Introduce a maximum width constraint for modes during validation. This ensures that the modes are filtered based on hardware capabilities, specifically addressing the line buffer limitations of individual pipes. Signed-off-by: Xiangxu Yin --- drivers/gpu/drm/msm/dp/dp_display.c | 3 +++ drivers/gpu/drm/msm/dp/dp_display.h | 1 + drivers/gpu/drm/msm/dp/dp_panel.c | 13 +++++++++++++ drivers/gpu/drm/msm/dp/dp_panel.h | 1 + 4 files changed, 18 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 4c83402fc7e0d41cb7621fa2efda043269d0a608..eb6fb76c68e505fafbec563440e9784f51e1894b 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -944,6 +944,9 @@ enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge, msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); link_info = &msm_dp_display->panel->link_info; + if (mode->hdisplay > msm_dp_display->panel->max_dp_width) + return MODE_BAD; + if (drm_mode_is_420_only(&dp->connector->display_info, mode) && msm_dp_display->panel->vsc_sdp_supported) mode_pclk_khz /= 2; diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index ecbc2d92f546a346ee53adcf1b060933e4f54317..7a11f7eeb691976f06afc7aff67650397d7deb90 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -11,6 +11,7 @@ #include "disp/msm_disp_snapshot.h" #define DP_MAX_PIXEL_CLK_KHZ 675000 +#define DP_MAX_WIDTH 7680 struct msm_dp { struct drm_device *drm_dev; diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 8654180aa259234bbd41f4f88c13c485f9791b1d..10501e301c5e073d8d34093b86a15d72e646a01f 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -4,6 +4,7 @@ */ #include "dp_panel.h" +#include "dp_display.h" #include "dp_utils.h" #include @@ -455,6 +456,16 @@ static u32 msm_dp_panel_link_frequencies(struct device_node *of_node) return frequency; } +static u32 msm_dp_panel_max_width(struct device_node *of_node) +{ + u32 max_width = 0; + + if (of_property_read_u32(of_node, "max-width", &max_width)) + max_width = DP_MAX_WIDTH; + + return max_width; +} + static int msm_dp_panel_parse_dt(struct msm_dp_panel *msm_dp_panel) { struct msm_dp_panel_private *panel; @@ -490,6 +501,8 @@ static int msm_dp_panel_parse_dt(struct msm_dp_panel *msm_dp_panel) if (!msm_dp_panel->max_dp_link_rate) msm_dp_panel->max_dp_link_rate = DP_LINK_RATE_HBR2; + msm_dp_panel->max_dp_width = msm_dp_panel_max_width(of_node); + return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 7603b92c32902bd3d4485539bd6308537ff75a2c..61513644161209c243bbb623ee4ded951b2a0597 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -51,6 +51,7 @@ struct msm_dp_panel { u32 lane_map[DP_MAX_NUM_DP_LANES]; u32 max_dp_lanes; u32 max_dp_link_rate; + u32 max_dp_width; u32 max_bw_code; }; From patchwork Fri Nov 29 07:57:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiangxu Yin X-Patchwork-Id: 13888470 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3E650D6EBE2 for ; Fri, 29 Nov 2024 07:59:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:CC:To:In-Reply-To:References:Message-ID :MIME-Version:Subject:Date:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=riSlEviBy0y9+ypimPDDjRXyazsfgvIffR6c2QCoALU=; b=qeAnWiqFnPH6Rm g4PEZRd7gUox0PIHxGf/fwJAl9N07yD3Ik5HRlkzwJWQIo34zS98s64+VhfTn/IrGcUVuU0SrnQSS 5MjPt8QTEDN5UqRLqKafvTCmJdclFoFlWToE9Fw9xssxdnm4Nf2zscQHfBn44eQ2BO2Cj8YkN1X+c YzuNrpcH+fIM+dDVdqoVFMZn+6Lc1T4d/BP0uRwVbrFcNEzFdzeA6PciOo8Pt4r5j3Wrmb/DCb0Br VQ8fUk0Px0yjpFVc6y8DzKXNGeWxryDvgELeg3y/DBbwLi5P1Hl19NBgq119r0AWH2LVLujOrk7WM G7iiIgmR/ChAgluVk4iQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tGvuf-0000000H7RA-020B; Fri, 29 Nov 2024 07:59:41 +0000 Received: from mx0a-0031df01.pphosted.com ([205.220.168.131]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tGvub-0000000H7Q3-23GJ for linux-phy@lists.infradead.org; Fri, 29 Nov 2024 07:59:39 +0000 Received: from pps.filterd (m0279867.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4ASNS0BH008537; Fri, 29 Nov 2024 07:59:31 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= II2/7psObqJRlsSmixY+Ggt+3kD1fPFPDHteJnLJoHc=; b=H8YhtMSofNZ6wBac xEJmiE9/FZ/HnqhWSLDYINaSimBS9JGLL1i76U46rJ78/sQ8ccGYuNhxMBTWMWdx 1IZxG+eKQ79WAcBNEgYhXQP9HPmtCmaIyB7BhqRLatxKRCda26gaJR4i4ojv7ZB7 kEltlPEvszeoEmlQCWH/6Kn6LfE5IjCoV1UYmSiH/rqQ/7oihlw2OraWIuTv+zzK QnxW1T/KSERx8T5LxTfwfjIIkrkalmY3lyTD7znSteQiNZ1RD5WDMrR6s/56/5WR ej5nP7l9/3MK0vXTECuR0n0h+5tuU5OUdoaWiwwPISJPwfjiMmD3oIX9Fu7hUbGk WHQwbg== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4366xw4uk3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:59:31 +0000 (GMT) Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AT7xUot002405 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:59:30 GMT Received: from szioemm-lnxbld002.qualcomm.com (10.80.80.8) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 28 Nov 2024 23:59:23 -0800 From: Xiangxu Yin Date: Fri, 29 Nov 2024 15:57:47 +0800 Subject: [PATCH 7/8] drm/msm/dp: Retry Link Training 2 with lower pattern MIME-Version: 1.0 Message-ID: <20241129-add-displayport-support-for-qcs615-platform-v1-7-09a4338d93ef@quicinc.com> References: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> In-Reply-To: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> To: Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Kuogee Hsieh , Vinod Koul , Kishon Vijay Abraham I , Linus Walleij , Bartosz Golaszewski , , CC: , , , , , , , Xiangxu Yin X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732867104; l=2567; i=quic_xiangxuy@quicinc.com; s=20241125; h=from:subject:message-id; bh=8/3LW4+HPMUH3aM6Hz1Gx/rY/UZuscAxr5Yaled+Z7o=; b=G3+ykvG9P/7rP22hO6S3tlsV/sAxb9L6sNlRmGe1v6SRTHRQd/4A7dZQFnEDkI9H1iMJIWDpA YoDSHhmniFEBhv6kKCHT07eU5pb/szmuB54w515UGd7NOEWik1Oh+Kb X-Developer-Key: i=quic_xiangxuy@quicinc.com; a=ed25519; pk=F1TwipJzpywfbt3n/RPi4l/A4AVF+QC89XzCHgZYaOc= X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: rYGwnjnVYvOgnDwaNjXYrSxj40c4jqrs X-Proofpoint-ORIG-GUID: rYGwnjnVYvOgnDwaNjXYrSxj40c4jqrs X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 malwarescore=0 bulkscore=0 impostorscore=0 priorityscore=1501 clxscore=1011 mlxlogscore=999 phishscore=0 adultscore=0 spamscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2411290064 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241128_235937_548537_2D5CC7C8 X-CRM114-Status: GOOD ( 14.44 ) X-BeenThere: linux-phy@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux Phy Mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-phy" Errors-To: linux-phy-bounces+linux-phy=archiver.kernel.org@lists.infradead.org Add a mechanism to retry Link Training 2 by lowering the pattern level when the link training #2 first attempt fails. This approach enhances compatibility, particularly addressing issues caused by certain hub configurations. Signed-off-by: Xiangxu Yin --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 49c8ce9b2d0e57a613e50865be3fe98e814d425a..b1862294cb98c9f756b0108b7670cb42de37bae4 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1220,7 +1220,7 @@ static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl) } static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, - int *training_step) + int *training_step, bool downgrade) { int tries = 0, ret = 0; u8 pattern; @@ -1243,6 +1243,28 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, state_ctrl_bit = 2; } + /* + * DP link training uses the highest allowed pattern by default. + * If it fails, the pattern is downgraded to improve cable and monitor compatibility. + */ + if (downgrade) { + switch (pattern) { + case DP_TRAINING_PATTERN_4: + pattern = DP_TRAINING_PATTERN_3; + state_ctrl_bit = 3; + break; + case DP_TRAINING_PATTERN_3: + pattern = DP_TRAINING_PATTERN_2; + state_ctrl_bit = 2; + break; + default: + break; + } + } + + drm_dbg_dp(ctrl->drm_dev, "pattern(%d) state_ctrl_bit(%d) downgrade(%d)\n", + pattern, state_ctrl_bit, downgrade); + ret = msm_dp_catalog_ctrl_set_pattern_state_bit(ctrl->catalog, state_ctrl_bit); if (ret) return ret; @@ -1311,10 +1333,14 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, /* print success info as this is a result of user initiated action */ drm_dbg_dp(ctrl->drm_dev, "link training #1 successful\n"); - ret = msm_dp_ctrl_link_train_2(ctrl, training_step); + ret = msm_dp_ctrl_link_train_2(ctrl, training_step, false); if (ret) { - DRM_ERROR("link training #2 failed. ret=%d\n", ret); - goto end; + drm_dbg_dp(ctrl->drm_dev, "link training #2 failed, retry downgrade.\n"); + ret = msm_dp_ctrl_link_train_2(ctrl, training_step, true); + if (ret) { + DRM_ERROR("link training #2 failed. ret=%d\n", ret); + goto end; + } } /* print success info as this is a result of user initiated action */ From patchwork Fri Nov 29 07:57:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiangxu Yin X-Patchwork-Id: 13888471 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7E31FD6EBE5 for ; Fri, 29 Nov 2024 07:59:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:CC:To:In-Reply-To:References:Message-ID :MIME-Version:Subject:Date:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=0enRfVPeeOaevt5xq3eMs9I48fHDC+nuDe2c1aii5g0=; b=TLGCgVuqLJIuDN xijefNDXv0LK+puA+7fLvXv7Tr4n304+s3YYNoFOMbWjq2eeeSfjg7IwS/bxcZldC0MM/Lkkgd1Ox CQ3CnX/s6UbjMhLfQ8Gf0nE2ReKp0c5KyxrY0AVKdMchtfEgs4yTG0JgYF00JktKBLWLcKSekuowg 7bBw548T/Gyrry8HXAXQKucVBtW6sQs20gsVMr8NhFpXGj5g5uLOYl4zn74SOoyY4xjlK29TCGKs6 wbx5Q8aUVt+GLwzm52pRVK8CWY6M89hic7c2rjafuQ31eK8q96C5JV0wc4//ZorQ8MV89Da0D0Dda vFfYCgj3TfDrhi8m7W+A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tGvul-0000000H7Tf-19QT; Fri, 29 Nov 2024 07:59:47 +0000 Received: from mx0a-0031df01.pphosted.com ([205.220.168.131]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tGvuj-0000000H7Sl-1FN8 for linux-phy@lists.infradead.org; Fri, 29 Nov 2024 07:59:46 +0000 Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4ASLZ99Q011311; Fri, 29 Nov 2024 07:59:39 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= c2W5Jc9ESQZPhwrskfSZmD27wZzekj5ji0rlq1whTWk=; b=cV8Fl2j8DMOopiNE UW7BXAQ25HNQqcOyuJMxhWbsueCOQA1DSwYJxTls/gTjEDQ5X1K+GmFfCiQEB0FB rsVlcVwMgwGLTd+YJRrRIs40USOUcXr9BmUJCj8/5xtGTkyqPjnVYzYy170fVrrw HZPvb/XwDKYOQPkLEIugkdpE6rVQLi4FOsnP9xWdizWRIlErL2SBEVdgyRJ18Onk Hz0NxpEGj06e3/ID7U+dhkGQnxmfrGTyInI+U6SJMPMHYACe/+TcBv1GIQJgvANh 0PafrbG8+UOao9rniOPnm3irQqSmZIipKlYfKfTAYBOJAL7Pahz4ZwBGgwKqjU8s X5PNyA== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4366xw4vny-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:59:39 +0000 (GMT) Received: from nasanex01c.na.qualcomm.com (nasanex01c.na.qualcomm.com [10.45.79.139]) by NASANPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4AT7xc4q002890 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Nov 2024 07:59:38 GMT Received: from szioemm-lnxbld002.qualcomm.com (10.80.80.8) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Thu, 28 Nov 2024 23:59:31 -0800 From: Xiangxu Yin Date: Fri, 29 Nov 2024 15:57:48 +0800 Subject: [PATCH 8/8] drm/msm/dp: Support external GPIO HPD with 3rd pinctrl chip MIME-Version: 1.0 Message-ID: <20241129-add-displayport-support-for-qcs615-platform-v1-8-09a4338d93ef@quicinc.com> References: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> In-Reply-To: <20241129-add-displayport-support-for-qcs615-platform-v1-0-09a4338d93ef@quicinc.com> To: Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Kuogee Hsieh , Vinod Koul , Kishon Vijay Abraham I , Linus Walleij , Bartosz Golaszewski , , CC: , , , , , , , Xiangxu Yin X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1732867105; l=4469; i=quic_xiangxuy@quicinc.com; s=20241125; h=from:subject:message-id; bh=TNj5EiTOMzDJ0PKM4MIWEv3ufyXXV6h9punYRpWZDKc=; b=GyogZ628z9aZFe6b5wiADpPghpaIkxyLi/0Kuotl2chQMlWFKmVE/aM4lLc3LE7wf4wgiLMzs rqlHSHvRfzSDJpXyO6xaLLA2qfSCX6d7te4ywU7ad1sP8ogKOFVa8sD X-Developer-Key: i=quic_xiangxuy@quicinc.com; a=ed25519; pk=F1TwipJzpywfbt3n/RPi4l/A4AVF+QC89XzCHgZYaOc= X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nasanex01c.na.qualcomm.com (10.45.79.139) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: O8LqOFgAl-AgO4VTrSQFKu8WR8dshWwy X-Proofpoint-ORIG-GUID: O8LqOFgAl-AgO4VTrSQFKu8WR8dshWwy X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 impostorscore=0 bulkscore=0 adultscore=0 suspectscore=0 mlxlogscore=999 mlxscore=0 spamscore=0 malwarescore=0 lowpriorityscore=0 priorityscore=1501 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2411120000 definitions=main-2411290064 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241128_235945_351211_B2CE3C42 X-CRM114-Status: GOOD ( 19.21 ) X-BeenThere: linux-phy@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux Phy Mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-phy" Errors-To: linux-phy-bounces+linux-phy=archiver.kernel.org@lists.infradead.org Add support for handling HPD (Hot Plug Detect) signals via external GPIOs connected through pinctrl chips (e.g., Semtech SX1509Q). This involves reinitializing the relevant GPIO and binding an interrupt handler to process hot plug events. Since external GPIOs only support edge interrupts (rising or falling) rather than state interrupts, the GPIO state must be read during the first DP bridge HPD enablement. This ensures the current connection state is determined and a hot plug event is reported accordingly. Signed-off-by: Xiangxu Yin --- drivers/gpu/drm/msm/dp/dp_display.c | 83 +++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index eb6fb76c68e505fafbec563440e9784f51e1894b..22c288ca61b9b444a7b8d4a574c614bfef9d88be 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include "msm_drv.h" #include "msm_kms.h" @@ -78,6 +80,10 @@ struct msm_dp_display_private { unsigned int id; + bool ext_gpio; + int gpio_num; + struct work_struct gpio_work; + /* state variables */ bool core_initialized; bool phy_initialized; @@ -1182,6 +1188,42 @@ static irqreturn_t msm_dp_display_irq_handler(int irq, void *dev_id) return ret; } + +static void msm_dp_gpio_work_handler(struct work_struct *work) +{ + struct msm_dp_display_private *dp = container_of(work, + struct msm_dp_display_private, gpio_work); + struct gpio_desc *desc; + bool hpd; + + if (dp->ext_gpio) { + desc = gpio_to_desc(dp->gpio_num); + if (!desc) { + pr_err("Failed to get gpio_desc for GPIO %d\n", dp->gpio_num); + return; + } + + hpd = gpiod_get_value_cansleep(desc); + if (hpd) + msm_dp_add_event(dp, EV_HPD_PLUG_INT, 0, 0); + else + msm_dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0); + } +} + +static irqreturn_t msm_dp_gpio_isr(int unused, void *data) +{ + struct msm_dp_display_private *dp = data; + + if (!dp) { + DRM_ERROR("NULL data\n"); + return IRQ_NONE; + } + + schedule_work(&dp->gpio_work); + return IRQ_HANDLED; +} + static int msm_dp_display_request_irq(struct msm_dp_display_private *dp) { int rc = 0; @@ -1193,6 +1235,21 @@ static int msm_dp_display_request_irq(struct msm_dp_display_private *dp) return dp->irq; } + if (dp->ext_gpio) { + int edge, gpio_irq; + + gpio_irq = gpio_to_irq(dp->gpio_num); + edge = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING; + + rc = devm_request_threaded_irq(&pdev->dev, gpio_irq, NULL, + msm_dp_gpio_isr, edge, "dp_gpio_isr", dp); + if (rc < 0) { + DRM_ERROR("failed to request ext-gpio IRQ%u: %d\n", + gpio_irq, rc); + return rc; + } + } + rc = devm_request_irq(&pdev->dev, dp->irq, msm_dp_display_irq_handler, IRQF_TRIGGER_HIGH|IRQF_NO_AUTOEN, "dp_display_isr", dp); @@ -1308,10 +1365,32 @@ static int msm_dp_display_probe(struct platform_device *pdev) return -EPROBE_DEFER; } + if (of_find_property(pdev->dev.of_node, "dp-hpd-gpio", NULL)) { + dp->ext_gpio = true; + dp->gpio_num = of_get_named_gpio(pdev->dev.of_node, "dp-hpd-gpio", 0); + if (dp->gpio_num < 0) { + dev_err(&pdev->dev, "Failed to get gpio:%d\n", dp->gpio_num); + return dp->gpio_num; + } + + if (!gpio_is_valid(dp->gpio_num)) { + DRM_ERROR("gpio(%d) invalid\n", dp->gpio_num); + return -EINVAL; + } + + rc = gpio_request(dp->gpio_num, "dp-hpd-gpio"); + if (rc) { + dev_err(&pdev->dev, "Failed to request gpio:%d\n", dp->gpio_num); + return rc; + } + gpio_direction_input(dp->gpio_num); + } + /* setup event q */ mutex_init(&dp->event_mutex); init_waitqueue_head(&dp->event_q); spin_lock_init(&dp->event_lock); + INIT_WORK(&dp->gpio_work, msm_dp_gpio_work_handler); /* Store DP audio handle inside DP display */ dp->msm_dp_display.msm_dp_audio = dp->audio; @@ -1678,6 +1757,10 @@ void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge) msm_dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, true); msm_dp_display->internal_hpd = true; + + if (dp->ext_gpio) + schedule_work(&dp->gpio_work); + mutex_unlock(&dp->event_mutex); }