From patchwork Wed Jul 24 15:01:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Gonzalez X-Patchwork-Id: 814633 Received: from ns.iliad.fr (ns.iliad.fr [212.27.33.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D489615B0EB; Wed, 24 Jul 2024 15:11:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.27.33.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721833885; cv=none; b=FCEt1aXyjYLT5gUd4Ww/nXMBaNv1HPELQMaqs5oY9pE9PAtKS6eVgH+Z+2e7yYFBnpHLTVxur6Dn271sDIxHUBzbIot7l53ydQew2DSTCx7IV5nAljKKpTm+4BlZ6HHJZM3R0UEsE06O6eaMtp1o+Qv+YOExnf/B/VZlb/bct6s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721833885; c=relaxed/simple; bh=2/bo7KZJP74rbBeLsAbEQGCUPWoqdQWGqwsdwfCL/60=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qw7O50qq5W/ReHLQUKC/P1Y8bQ/i7nsVRU9G6fcSXqm737ooLDHY4tXTM5YlUzfcS/U4QE8KZW3YGLKYBnGP71JNeXzeu3uucWYm2xOBCM5rylzyRuEpiJqBxQh82UXrHFbaKApHMlFkriYclGWY6sJryAACO+H1mgkgY7DfnOI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=freebox.fr; spf=pass smtp.mailfrom=srs.iliad.fr; arc=none smtp.client-ip=212.27.33.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=freebox.fr Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=srs.iliad.fr Received: from ns.iliad.fr (localhost [127.0.0.1]) by ns.iliad.fr (Postfix) with ESMTP id F0DA020824; Wed, 24 Jul 2024 17:01:54 +0200 (CEST) Received: from [127.0.1.1] (freebox.vlq16.iliad.fr [213.36.7.13]) by ns.iliad.fr (Postfix) with ESMTP id DBA4D2057C; Wed, 24 Jul 2024 17:01:54 +0200 (CEST) From: Marc Gonzalez Date: Wed, 24 Jul 2024 17:01:34 +0200 Subject: [PATCH v7 1/6] dt-bindings: phy: add qcom,hdmi-phy-8998 Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240724-hdmi-tx-v7-1-e44a20553464@freebox.fr> References: <20240724-hdmi-tx-v7-0-e44a20553464@freebox.fr> In-Reply-To: <20240724-hdmi-tx-v7-0-e44a20553464@freebox.fr> To: Vinod Koul , Kishon Vijay Abraham I , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , David Airlie , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Bjorn Andersson , Konrad Dybcio Cc: linux-arm-msm@vger.kernel.org, linux-phy@lists.infradead.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, Arnaud Vrac , Pierre-Hugues Husson , Jeffrey Hugo , Marc Gonzalez X-Mailer: b4 0.13.0 HDMI PHY block embedded in the APQ8098. Acked-by: Rob Herring (Arm) Acked-by: Vinod Koul Signed-off-by: Marc Gonzalez --- Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml b/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml index 83fe4b39b56f4..78607ee3e2e84 100644 --- a/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,hdmi-phy-qmp.yaml @@ -14,6 +14,7 @@ properties: compatible: enum: - qcom,hdmi-phy-8996 + - qcom,hdmi-phy-8998 reg: maxItems: 6 From patchwork Wed Jul 24 15:01:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Gonzalez X-Patchwork-Id: 814204 Received: from ns.iliad.fr (ns.iliad.fr [212.27.33.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D47F4159583; Wed, 24 Jul 2024 15:11:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.27.33.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721833884; cv=none; b=jCI84OjPZM9rhNeRq7zMgwc5F0aYf7KTk/nOdT54CAgHz+fbxsCs2K6hQs19NbIzc+UK7mUg7/PG5PnHzrjX7OOEbjmUXs+Eh13z9DU3PhIfE9NHaQY+PnG5znz+bYnEwlmhWXCpyQ2Sglge5ERuJcUh871xfd2AiIIY1FrfRJ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721833884; c=relaxed/simple; bh=JsmDHlk5+eiTop7eiw22HLUqgaUiSavt6dPNugqf0iY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DVxYQ+MZ08nXg187jbrEXLCtQ4dFcpq8yW/+Te/wkZ5RA9uzntDo+MjNa35VmV7YnRRrgS4XoROa3WbfW3qPCjqIBUNTjegXpWmlMCorWnPA2sNwXm0jVmBFAy6vbotL4NG+flMYpAHraclyvLllgdqdMWeQlcnP6czoVvEbDSs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=freebox.fr; spf=pass smtp.mailfrom=srs.iliad.fr; arc=none smtp.client-ip=212.27.33.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=freebox.fr Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=srs.iliad.fr Received: from ns.iliad.fr (localhost [127.0.0.1]) by ns.iliad.fr (Postfix) with ESMTP id 0576520871; Wed, 24 Jul 2024 17:01:55 +0200 (CEST) Received: from [127.0.1.1] (freebox.vlq16.iliad.fr [213.36.7.13]) by ns.iliad.fr (Postfix) with ESMTP id E5F692060E; Wed, 24 Jul 2024 17:01:54 +0200 (CEST) From: Marc Gonzalez Date: Wed, 24 Jul 2024 17:01:35 +0200 Subject: [PATCH v7 2/6] dt-bindings: display/msm: hdmi: add qcom,hdmi-tx-8998 Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240724-hdmi-tx-v7-2-e44a20553464@freebox.fr> References: <20240724-hdmi-tx-v7-0-e44a20553464@freebox.fr> In-Reply-To: <20240724-hdmi-tx-v7-0-e44a20553464@freebox.fr> To: Vinod Koul , Kishon Vijay Abraham I , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , David Airlie , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Bjorn Andersson , Konrad Dybcio Cc: linux-arm-msm@vger.kernel.org, linux-phy@lists.infradead.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, Arnaud Vrac , Pierre-Hugues Husson , Jeffrey Hugo , Conor Dooley , Marc Gonzalez X-Mailer: b4 0.13.0 HDMI TX block embedded in the APQ8098. Reviewed-by: Rob Herring (Arm) Reviewed-by: Conor Dooley Signed-off-by: Marc Gonzalez --- .../devicetree/bindings/display/msm/hdmi.yaml | 28 ++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/hdmi.yaml b/Documentation/devicetree/bindings/display/msm/hdmi.yaml index 47e97669821c3..d4a2033afea8d 100644 --- a/Documentation/devicetree/bindings/display/msm/hdmi.yaml +++ b/Documentation/devicetree/bindings/display/msm/hdmi.yaml @@ -19,14 +19,15 @@ properties: - qcom,hdmi-tx-8974 - qcom,hdmi-tx-8994 - qcom,hdmi-tx-8996 + - qcom,hdmi-tx-8998 clocks: minItems: 1 - maxItems: 5 + maxItems: 8 clock-names: minItems: 1 - maxItems: 5 + maxItems: 8 reg: minItems: 1 @@ -142,6 +143,7 @@ allOf: properties: clocks: minItems: 5 + maxItems: 5 clock-names: items: - const: mdp_core @@ -151,6 +153,28 @@ allOf: - const: extp hdmi-mux-supplies: false + - if: + properties: + compatible: + contains: + enum: + - qcom,hdmi-tx-8998 + then: + properties: + clocks: + minItems: 8 + maxItems: 8 + clock-names: + items: + - const: mdp_core + - const: iface + - const: core + - const: alt_iface + - const: extp + - const: bus + - const: mnoc + - const: iface_mmss + additionalProperties: false examples: From patchwork Wed Jul 24 15:01:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Gonzalez X-Patchwork-Id: 814635 Received: from ns.iliad.fr (ns.iliad.fr [212.27.33.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D4757155739; Wed, 24 Jul 2024 15:11:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.27.33.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721833884; cv=none; b=qQGTG7mT6gAHu2X22UljUeTrjAzFlVF4Er68Ux6B9wewNTSXxjInN9CvDhHSOQsc1C2EFqNvPfAB0M1cG1AA9HA7BiXLKxiyjp2E+4298XDZjZUdZ6d9c+GmiY+6lfVJ0gBAr4tCPj6gqUMJBM12UCkRe/AYEe2Iw2juOQtNMjI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721833884; c=relaxed/simple; bh=hVOBMR0WMRaGugqwkxG5LTFeTAvlAEfxXnR4loSOMw4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Wc3Ht4/bYQ7PWGfR1iLdQ+RCYLqRXyd99dctl7T/sOPnTs3dBtnstgzHLvFtCiT4dA5RcS//1CDeen4ByeyoSxkvhvfWQYxWXAVZSMbeP5ZQh1oEJtJGukgrnwava7DZVgAe8ADq9NZsyaqBBtOo07Ar626roF7EGJtKTZtwoWY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=freebox.fr; spf=pass smtp.mailfrom=srs.iliad.fr; arc=none smtp.client-ip=212.27.33.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=freebox.fr Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=srs.iliad.fr Received: from ns.iliad.fr (localhost [127.0.0.1]) by ns.iliad.fr (Postfix) with ESMTP id 0E56E208A3; Wed, 24 Jul 2024 17:01:55 +0200 (CEST) Received: from [127.0.1.1] (freebox.vlq16.iliad.fr [213.36.7.13]) by ns.iliad.fr (Postfix) with ESMTP id EE7942081E; Wed, 24 Jul 2024 17:01:54 +0200 (CEST) From: Marc Gonzalez Date: Wed, 24 Jul 2024 17:01:36 +0200 Subject: [PATCH v7 3/6] drm/msm/hdmi: add "qcom,hdmi-tx-8998" compatible Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240724-hdmi-tx-v7-3-e44a20553464@freebox.fr> References: <20240724-hdmi-tx-v7-0-e44a20553464@freebox.fr> In-Reply-To: <20240724-hdmi-tx-v7-0-e44a20553464@freebox.fr> To: Vinod Koul , Kishon Vijay Abraham I , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , David Airlie , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Bjorn Andersson , Konrad Dybcio Cc: linux-arm-msm@vger.kernel.org, linux-phy@lists.infradead.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, Arnaud Vrac , Pierre-Hugues Husson , Jeffrey Hugo , Marc Gonzalez X-Mailer: b4 0.13.0 Current driver already supports the msm8998 HDMI TX. We just need to add the compatible string. Reviewed-by: Dmitry Baryshkov Signed-off-by: Marc Gonzalez --- drivers/gpu/drm/msm/hdmi/hdmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 24abcb7254cc4..0bfee41c2e71a 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -549,6 +549,7 @@ static void msm_hdmi_dev_remove(struct platform_device *pdev) } static const struct of_device_id msm_hdmi_dt_match[] = { + { .compatible = "qcom,hdmi-tx-8998", .data = &hdmi_tx_8974_config }, { .compatible = "qcom,hdmi-tx-8996", .data = &hdmi_tx_8974_config }, { .compatible = "qcom,hdmi-tx-8994", .data = &hdmi_tx_8974_config }, { .compatible = "qcom,hdmi-tx-8084", .data = &hdmi_tx_8974_config }, From patchwork Wed Jul 24 15:01:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Gonzalez X-Patchwork-Id: 814203 Received: from ns.iliad.fr (ns.iliad.fr [212.27.33.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D483615ADB1; Wed, 24 Jul 2024 15:11:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.27.33.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721833885; cv=none; b=hfzAY1zQUJgBi2arwE/5MiPjDVs49ZIxdFA5uCT9rGzxzdCABR3fTowCEykiQcwKa3WqQ2WRvvzCCo2JQz/NKNU6OmHR6ung7tG+e1g+XCfG/CKj2FwE+688nETNhMmVFZmDg98U9YuGLWiKCuXrAwMAr9ebwi3+rTp4slH98Rk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721833885; c=relaxed/simple; bh=ehv49nSWHu5SIni58KmoErB+ElgkZDBgbbx9CuycqQg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=n+paT0Bko+ezvBb3LDdu4feWylHU71PPkhC9sh8T+X36VsnOzhKy0BWzYyoEsuzFLUGH0YYt+c1G3f6aJibrqA68v5tN5lMlOLG8eExqE/U2YdBRgGStKW+egKeefTGrMgepVQOn48Qq3khFrKmrTQnI9Oec3JpU3HqeuBQ4c4Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=freebox.fr; spf=pass smtp.mailfrom=srs.iliad.fr; arc=none smtp.client-ip=212.27.33.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=freebox.fr Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=srs.iliad.fr Received: from ns.iliad.fr (localhost [127.0.0.1]) by ns.iliad.fr (Postfix) with ESMTP id 15E3B2096E; Wed, 24 Jul 2024 17:01:55 +0200 (CEST) Received: from [127.0.1.1] (freebox.vlq16.iliad.fr [213.36.7.13]) by ns.iliad.fr (Postfix) with ESMTP id 031132086C; Wed, 24 Jul 2024 17:01:55 +0200 (CEST) From: Marc Gonzalez Date: Wed, 24 Jul 2024 17:01:37 +0200 Subject: [PATCH v7 4/6] drm/msm: add msm8998 hdmi phy/pll support Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240724-hdmi-tx-v7-4-e44a20553464@freebox.fr> References: <20240724-hdmi-tx-v7-0-e44a20553464@freebox.fr> In-Reply-To: <20240724-hdmi-tx-v7-0-e44a20553464@freebox.fr> To: Vinod Koul , Kishon Vijay Abraham I , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , David Airlie , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Bjorn Andersson , Konrad Dybcio Cc: linux-arm-msm@vger.kernel.org, linux-phy@lists.infradead.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, Arnaud Vrac , Pierre-Hugues Husson , Jeffrey Hugo , Marc Gonzalez X-Mailer: b4 0.13.0 From: Arnaud Vrac Add support for the HDMI PHY as present on the Qualcomm MSM8998 SoC. This code is mostly copy & paste of the vendor code from msm-4.4 kernel.lnx.4.4.r38-rel. Signed-off-by: Arnaud Vrac Reviewed-by: Dmitry Baryshkov Signed-off-by: Marc Gonzalez --- drivers/gpu/drm/msm/Makefile | 1 + drivers/gpu/drm/msm/hdmi/hdmi.h | 8 + drivers/gpu/drm/msm/hdmi/hdmi_phy.c | 5 + drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c | 779 +++++++++++++++++++++++++ drivers/gpu/drm/msm/registers/display/hdmi.xml | 89 +++ 5 files changed, 882 insertions(+) diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index eb788921ff4fe..b9a5dc8c33ede 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -32,6 +32,7 @@ msm-display-$(CONFIG_DRM_MSM_HDMI) += \ hdmi/hdmi_phy.o \ hdmi/hdmi_phy_8960.o \ hdmi/hdmi_phy_8996.o \ + hdmi/hdmi_phy_8998.o \ hdmi/hdmi_phy_8x60.o \ hdmi/hdmi_phy_8x74.o \ hdmi/hdmi_pll_8960.o \ diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index 4586baf364151..a62d2aedfbb72 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -137,6 +137,7 @@ enum hdmi_phy_type { MSM_HDMI_PHY_8960, MSM_HDMI_PHY_8x74, MSM_HDMI_PHY_8996, + MSM_HDMI_PHY_8998, MSM_HDMI_PHY_MAX, }; @@ -154,6 +155,7 @@ extern const struct hdmi_phy_cfg msm_hdmi_phy_8x60_cfg; extern const struct hdmi_phy_cfg msm_hdmi_phy_8960_cfg; extern const struct hdmi_phy_cfg msm_hdmi_phy_8x74_cfg; extern const struct hdmi_phy_cfg msm_hdmi_phy_8996_cfg; +extern const struct hdmi_phy_cfg msm_hdmi_phy_8998_cfg; struct hdmi_phy { struct platform_device *pdev; @@ -184,6 +186,7 @@ void __exit msm_hdmi_phy_driver_unregister(void); #ifdef CONFIG_COMMON_CLK int msm_hdmi_pll_8960_init(struct platform_device *pdev); int msm_hdmi_pll_8996_init(struct platform_device *pdev); +int msm_hdmi_pll_8998_init(struct platform_device *pdev); #else static inline int msm_hdmi_pll_8960_init(struct platform_device *pdev) { @@ -194,6 +197,11 @@ static inline int msm_hdmi_pll_8996_init(struct platform_device *pdev) { return -ENODEV; } + +static inline int msm_hdmi_pll_8998_init(struct platform_device *pdev) +{ + return -ENODEV; +} #endif /* diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c index 88a3423b7f24d..95b3f7535d840 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c @@ -118,6 +118,9 @@ static int msm_hdmi_phy_pll_init(struct platform_device *pdev, case MSM_HDMI_PHY_8996: ret = msm_hdmi_pll_8996_init(pdev); break; + case MSM_HDMI_PHY_8998: + ret = msm_hdmi_pll_8998_init(pdev); + break; /* * we don't have PLL support for these, don't report an error for now */ @@ -193,6 +196,8 @@ static const struct of_device_id msm_hdmi_phy_dt_match[] = { .data = &msm_hdmi_phy_8x74_cfg }, { .compatible = "qcom,hdmi-phy-8996", .data = &msm_hdmi_phy_8996_cfg }, + { .compatible = "qcom,hdmi-phy-8998", + .data = &msm_hdmi_phy_8998_cfg }, {} }; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c new file mode 100644 index 0000000000000..9a3b005fa391a --- /dev/null +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c @@ -0,0 +1,779 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2024 Freebox SAS + */ + +#include +#include + +#include "hdmi.h" + +#define HDMI_VCO_MAX_FREQ 12000000000UL +#define HDMI_VCO_MIN_FREQ 8000000000UL + +#define HDMI_PCLK_MAX_FREQ 600000000 +#define HDMI_PCLK_MIN_FREQ 25000000 + +#define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD 3400000000UL +#define HDMI_DIG_FREQ_BIT_CLK_THRESHOLD 1500000000UL +#define HDMI_MID_FREQ_BIT_CLK_THRESHOLD 750000000UL +#define HDMI_CORECLK_DIV 5 +#define HDMI_DEFAULT_REF_CLOCK 19200000 +#define HDMI_PLL_CMP_CNT 1024 + +#define HDMI_PLL_POLL_MAX_READS 100 +#define HDMI_PLL_POLL_TIMEOUT_US 150 + +#define HDMI_NUM_TX_CHANNEL 4 + +struct hdmi_pll_8998 { + struct platform_device *pdev; + struct clk_hw clk_hw; + unsigned long rate; + + /* pll mmio base */ + void __iomem *mmio_qserdes_com; + /* tx channel base */ + void __iomem *mmio_qserdes_tx[HDMI_NUM_TX_CHANNEL]; +}; + +#define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8998, clk_hw) + +struct hdmi_8998_phy_pll_reg_cfg { + u32 com_svs_mode_clk_sel; + u32 com_hsclk_sel; + u32 com_pll_cctrl_mode0; + u32 com_pll_rctrl_mode0; + u32 com_cp_ctrl_mode0; + u32 com_dec_start_mode0; + u32 com_div_frac_start1_mode0; + u32 com_div_frac_start2_mode0; + u32 com_div_frac_start3_mode0; + u32 com_integloop_gain0_mode0; + u32 com_integloop_gain1_mode0; + u32 com_lock_cmp_en; + u32 com_lock_cmp1_mode0; + u32 com_lock_cmp2_mode0; + u32 com_lock_cmp3_mode0; + u32 com_core_clk_en; + u32 com_coreclk_div_mode0; + + u32 tx_lx_tx_band[HDMI_NUM_TX_CHANNEL]; + u32 tx_lx_tx_drv_lvl[HDMI_NUM_TX_CHANNEL]; + u32 tx_lx_tx_emp_post1_lvl[HDMI_NUM_TX_CHANNEL]; + u32 tx_lx_pre_driver_1[HDMI_NUM_TX_CHANNEL]; + u32 tx_lx_pre_driver_2[HDMI_NUM_TX_CHANNEL]; + u32 tx_lx_res_code_offset[HDMI_NUM_TX_CHANNEL]; + + u32 phy_mode; +}; + +struct hdmi_8998_post_divider { + u64 vco_freq; + int hsclk_divsel; + int vco_ratio; + int tx_band_sel; + int half_rate_mode; +}; + +static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8998 *pll) +{ + return platform_get_drvdata(pll->pdev); +} + +static inline void hdmi_pll_write(struct hdmi_pll_8998 *pll, int offset, + u32 data) +{ + writel(data, pll->mmio_qserdes_com + offset); +} + +static inline u32 hdmi_pll_read(struct hdmi_pll_8998 *pll, int offset) +{ + return readl(pll->mmio_qserdes_com + offset); +} + +static inline void hdmi_tx_chan_write(struct hdmi_pll_8998 *pll, int channel, + int offset, int data) +{ + writel(data, pll->mmio_qserdes_tx[channel] + offset); +} + +static inline u32 pll_get_cpctrl(u64 frac_start, unsigned long ref_clk, + bool gen_ssc) +{ + if ((frac_start != 0) || gen_ssc) + return 0x8; + + return 0x30; +} + +static inline u32 pll_get_rctrl(u64 frac_start, bool gen_ssc) +{ + if ((frac_start != 0) || gen_ssc) + return 0x16; + + return 0x18; +} + +static inline u32 pll_get_cctrl(u64 frac_start, bool gen_ssc) +{ + if ((frac_start != 0) || gen_ssc) + return 0x34; + + return 0x2; +} + +static inline u32 pll_get_integloop_gain(u64 frac_start, u64 bclk, u32 ref_clk, + bool gen_ssc) +{ + int digclk_divsel = bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD ? 1 : 2; + u64 base; + + if ((frac_start != 0) || gen_ssc) + base = 0x3F; + else + base = 0xC4; + + base <<= (digclk_divsel == 2 ? 1 : 0); + + return (base <= 2046 ? base : 2046); +} + +static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk) +{ + u64 dividend = HDMI_PLL_CMP_CNT * fdata; + u32 divisor = ref_clk * 10; + u32 rem; + + rem = do_div(dividend, divisor); + if (rem > (divisor >> 1)) + dividend++; + + return dividend - 1; +} + +static inline u64 pll_cmp_to_fdata(u32 pll_cmp, unsigned long ref_clk) +{ + u64 fdata = ((u64)pll_cmp) * ref_clk * 10; + + do_div(fdata, HDMI_PLL_CMP_CNT); + + return fdata; +} + +#define HDMI_REF_CLOCK_HZ ((u64)19200000) +#define HDMI_MHZ_TO_HZ ((u64)1000000) +static int pll_get_post_div(struct hdmi_8998_post_divider *pd, u64 bclk) +{ + u32 const ratio_list[] = {1, 2, 3, 4, 5, 6, + 9, 10, 12, 15, 25}; + u32 const band_list[] = {0, 1, 2, 3}; + u32 const sz_ratio = ARRAY_SIZE(ratio_list); + u32 const sz_band = ARRAY_SIZE(band_list); + u32 const cmp_cnt = 1024; + u32 const th_min = 500, th_max = 1000; + u32 half_rate_mode = 0; + u32 list_elements; + int optimal_index; + u32 i, j, k; + u32 found_hsclk_divsel = 0, found_vco_ratio; + u32 found_tx_band_sel; + u64 const min_freq = HDMI_VCO_MIN_FREQ, max_freq = HDMI_VCO_MAX_FREQ; + u64 freq_list[ARRAY_SIZE(ratio_list) * ARRAY_SIZE(band_list)]; + u64 found_vco_freq; + u64 freq_optimal; + +find_optimal_index: + freq_optimal = max_freq; + optimal_index = -1; + list_elements = 0; + + for (i = 0; i < sz_ratio; i++) { + for (j = 0; j < sz_band; j++) { + u64 freq = div_u64(bclk, (1 << half_rate_mode)); + + freq *= (ratio_list[i] * (1 << band_list[j])); + freq_list[list_elements++] = freq; + } + } + + for (k = 0; k < ARRAY_SIZE(freq_list); k++) { + u32 const clks_pll_div = 2, core_clk_div = 5; + u32 const rng1 = 16, rng2 = 8; + u32 th1, th2; + u64 core_clk, rvar1, rem; + + core_clk = (((freq_list[k] / + ratio_list[k / sz_band]) / + clks_pll_div) / core_clk_div); + + rvar1 = HDMI_REF_CLOCK_HZ * rng1 * HDMI_MHZ_TO_HZ; + rvar1 = div64_u64_rem(rvar1, (cmp_cnt * core_clk), &rem); + if (rem > ((cmp_cnt * core_clk) >> 1)) + rvar1++; + th1 = rvar1; + + rvar1 = HDMI_REF_CLOCK_HZ * rng2 * HDMI_MHZ_TO_HZ; + rvar1 = div64_u64_rem(rvar1, (cmp_cnt * core_clk), &rem); + if (rem > ((cmp_cnt * core_clk) >> 1)) + rvar1++; + th2 = rvar1; + + if (freq_list[k] >= min_freq && + freq_list[k] <= max_freq) { + if ((th1 >= th_min && th1 <= th_max) || + (th2 >= th_min && th2 <= th_max)) { + if (freq_list[k] <= freq_optimal) { + freq_optimal = freq_list[k]; + optimal_index = k; + } + } + } + } + + if (optimal_index == -1) { + if (!half_rate_mode) { + half_rate_mode = 1; + goto find_optimal_index; + } else { + return -EINVAL; + } + } else { + found_vco_ratio = ratio_list[optimal_index / sz_band]; + found_tx_band_sel = band_list[optimal_index % sz_band]; + found_vco_freq = freq_optimal; + } + + switch (found_vco_ratio) { + case 1: + found_hsclk_divsel = 15; + break; + case 2: + found_hsclk_divsel = 0; + break; + case 3: + found_hsclk_divsel = 4; + break; + case 4: + found_hsclk_divsel = 8; + break; + case 5: + found_hsclk_divsel = 12; + break; + case 6: + found_hsclk_divsel = 1; + break; + case 9: + found_hsclk_divsel = 5; + break; + case 10: + found_hsclk_divsel = 2; + break; + case 12: + found_hsclk_divsel = 9; + break; + case 15: + found_hsclk_divsel = 13; + break; + case 25: + found_hsclk_divsel = 14; + break; + }; + + pd->vco_freq = found_vco_freq; + pd->tx_band_sel = found_tx_band_sel; + pd->vco_ratio = found_vco_ratio; + pd->hsclk_divsel = found_hsclk_divsel; + + return 0; +} + +static int pll_calculate(unsigned long pix_clk, unsigned long ref_clk, + struct hdmi_8998_phy_pll_reg_cfg *cfg) +{ + struct hdmi_8998_post_divider pd; + u64 bclk; + u64 dec_start; + u64 frac_start; + u64 fdata; + u32 pll_divisor; + u32 rem; + u32 cpctrl; + u32 rctrl; + u32 cctrl; + u32 integloop_gain; + u32 pll_cmp; + int i, ret; + + /* bit clk = 10 * pix_clk */ + bclk = ((u64)pix_clk) * 10; + + ret = pll_get_post_div(&pd, bclk); + if (ret) + return ret; + + dec_start = pd.vco_freq; + pll_divisor = 4 * ref_clk; + do_div(dec_start, pll_divisor); + + frac_start = pd.vco_freq * (1 << 20); + + rem = do_div(frac_start, pll_divisor); + frac_start -= dec_start * (1 << 20); + if (rem > (pll_divisor >> 1)) + frac_start++; + + cpctrl = pll_get_cpctrl(frac_start, ref_clk, false); + rctrl = pll_get_rctrl(frac_start, false); + cctrl = pll_get_cctrl(frac_start, false); + integloop_gain = pll_get_integloop_gain(frac_start, bclk, + ref_clk, false); + + fdata = pd.vco_freq; + do_div(fdata, pd.vco_ratio); + + pll_cmp = pll_get_pll_cmp(fdata, ref_clk); + + /* Convert these values to register specific values */ + if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD) + cfg->com_svs_mode_clk_sel = 1; + else + cfg->com_svs_mode_clk_sel = 2; + + cfg->com_hsclk_sel = (0x20 | pd.hsclk_divsel); + cfg->com_pll_cctrl_mode0 = cctrl; + cfg->com_pll_rctrl_mode0 = rctrl; + cfg->com_cp_ctrl_mode0 = cpctrl; + cfg->com_dec_start_mode0 = dec_start; + cfg->com_div_frac_start1_mode0 = (frac_start & 0xff); + cfg->com_div_frac_start2_mode0 = ((frac_start & 0xff00) >> 8); + cfg->com_div_frac_start3_mode0 = ((frac_start & 0xf0000) >> 16); + cfg->com_integloop_gain0_mode0 = (integloop_gain & 0xff); + cfg->com_integloop_gain1_mode0 = ((integloop_gain & 0xf00) >> 8); + cfg->com_lock_cmp1_mode0 = (pll_cmp & 0xff); + cfg->com_lock_cmp2_mode0 = ((pll_cmp & 0xff00) >> 8); + cfg->com_lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16); + cfg->com_lock_cmp_en = 0x0; + cfg->com_core_clk_en = 0x2c; + cfg->com_coreclk_div_mode0 = HDMI_CORECLK_DIV; + cfg->phy_mode = (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x5 : 0x4; + + for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) + cfg->tx_lx_tx_band[i] = pd.tx_band_sel; + + if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) { + cfg->tx_lx_tx_drv_lvl[0] = 0x0f; + cfg->tx_lx_tx_drv_lvl[1] = 0x0f; + cfg->tx_lx_tx_drv_lvl[2] = 0x0f; + cfg->tx_lx_tx_drv_lvl[3] = 0x0f; + cfg->tx_lx_tx_emp_post1_lvl[0] = 0x03; + cfg->tx_lx_tx_emp_post1_lvl[1] = 0x02; + cfg->tx_lx_tx_emp_post1_lvl[2] = 0x03; + cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00; + cfg->tx_lx_pre_driver_1[0] = 0x00; + cfg->tx_lx_pre_driver_1[1] = 0x00; + cfg->tx_lx_pre_driver_1[2] = 0x00; + cfg->tx_lx_pre_driver_1[3] = 0x00; + cfg->tx_lx_pre_driver_2[0] = 0x1C; + cfg->tx_lx_pre_driver_2[1] = 0x1C; + cfg->tx_lx_pre_driver_2[2] = 0x1C; + cfg->tx_lx_pre_driver_2[3] = 0x00; + cfg->tx_lx_res_code_offset[0] = 0x03; + cfg->tx_lx_res_code_offset[1] = 0x00; + cfg->tx_lx_res_code_offset[2] = 0x00; + cfg->tx_lx_res_code_offset[3] = 0x03; + } else if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD) { + cfg->tx_lx_tx_drv_lvl[0] = 0x0f; + cfg->tx_lx_tx_drv_lvl[1] = 0x0f; + cfg->tx_lx_tx_drv_lvl[2] = 0x0f; + cfg->tx_lx_tx_drv_lvl[3] = 0x0f; + cfg->tx_lx_tx_emp_post1_lvl[0] = 0x03; + cfg->tx_lx_tx_emp_post1_lvl[1] = 0x03; + cfg->tx_lx_tx_emp_post1_lvl[2] = 0x03; + cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00; + cfg->tx_lx_pre_driver_1[0] = 0x00; + cfg->tx_lx_pre_driver_1[1] = 0x00; + cfg->tx_lx_pre_driver_1[2] = 0x00; + cfg->tx_lx_pre_driver_1[3] = 0x00; + cfg->tx_lx_pre_driver_2[0] = 0x16; + cfg->tx_lx_pre_driver_2[1] = 0x16; + cfg->tx_lx_pre_driver_2[2] = 0x16; + cfg->tx_lx_pre_driver_2[3] = 0x18; + cfg->tx_lx_res_code_offset[0] = 0x03; + cfg->tx_lx_res_code_offset[1] = 0x00; + cfg->tx_lx_res_code_offset[2] = 0x00; + cfg->tx_lx_res_code_offset[3] = 0x00; + } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) { + cfg->tx_lx_tx_drv_lvl[0] = 0x0f; + cfg->tx_lx_tx_drv_lvl[1] = 0x0f; + cfg->tx_lx_tx_drv_lvl[2] = 0x0f; + cfg->tx_lx_tx_drv_lvl[3] = 0x0f; + cfg->tx_lx_tx_emp_post1_lvl[0] = 0x05; + cfg->tx_lx_tx_emp_post1_lvl[1] = 0x05; + cfg->tx_lx_tx_emp_post1_lvl[2] = 0x05; + cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00; + cfg->tx_lx_pre_driver_1[0] = 0x00; + cfg->tx_lx_pre_driver_1[1] = 0x00; + cfg->tx_lx_pre_driver_1[2] = 0x00; + cfg->tx_lx_pre_driver_1[3] = 0x00; + cfg->tx_lx_pre_driver_2[0] = 0x0E; + cfg->tx_lx_pre_driver_2[1] = 0x0E; + cfg->tx_lx_pre_driver_2[2] = 0x0E; + cfg->tx_lx_pre_driver_2[3] = 0x0E; + cfg->tx_lx_res_code_offset[0] = 0x00; + cfg->tx_lx_res_code_offset[1] = 0x00; + cfg->tx_lx_res_code_offset[2] = 0x00; + cfg->tx_lx_res_code_offset[3] = 0x00; + } else { + cfg->tx_lx_tx_drv_lvl[0] = 0x01; + cfg->tx_lx_tx_drv_lvl[1] = 0x01; + cfg->tx_lx_tx_drv_lvl[2] = 0x01; + cfg->tx_lx_tx_drv_lvl[3] = 0x00; + cfg->tx_lx_tx_emp_post1_lvl[0] = 0x00; + cfg->tx_lx_tx_emp_post1_lvl[1] = 0x00; + cfg->tx_lx_tx_emp_post1_lvl[2] = 0x00; + cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00; + cfg->tx_lx_pre_driver_1[0] = 0x00; + cfg->tx_lx_pre_driver_1[1] = 0x00; + cfg->tx_lx_pre_driver_1[2] = 0x00; + cfg->tx_lx_pre_driver_1[3] = 0x00; + cfg->tx_lx_pre_driver_2[0] = 0x16; + cfg->tx_lx_pre_driver_2[1] = 0x16; + cfg->tx_lx_pre_driver_2[2] = 0x16; + cfg->tx_lx_pre_driver_2[3] = 0x18; + cfg->tx_lx_res_code_offset[0] = 0x00; + cfg->tx_lx_res_code_offset[1] = 0x00; + cfg->tx_lx_res_code_offset[2] = 0x00; + cfg->tx_lx_res_code_offset[3] = 0x00; + } + + return 0; +} + +static int hdmi_8998_pll_set_clk_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw); + struct hdmi_phy *phy = pll_get_phy(pll); + struct hdmi_8998_phy_pll_reg_cfg cfg = {}; + int i, ret; + + ret = pll_calculate(rate, parent_rate, &cfg); + if (ret) { + DRM_ERROR("PLL calculation failed\n"); + return ret; + } + + /* Initially shut down PHY */ + hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0x0); + udelay(500); + + /* Power up sequence */ + hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0x1); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_RESETSM_CNTRL, 0x20); + hdmi_phy_write(phy, REG_HDMI_8998_PHY_CMN_CTRL, 0x6); + + for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(pll, i, + REG_HDMI_8998_PHY_TXn_INTERFACE_SELECT_TX_BAND, + cfg.tx_lx_tx_band[i]); + hdmi_tx_chan_write(pll, i, + REG_HDMI_8998_PHY_TXn_CLKBUF_TERM_ENABLE, + 0x1); + hdmi_tx_chan_write(pll, i, + REG_HDMI_8998_PHY_TXn_LANE_MODE, + 0x20); + } + + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYSCLK_BUF_ENABLE, 0x02); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x0B); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYSCLK_EN_SEL, 0x37); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYS_CLK_CTRL, 0x02); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CLK_ENABLE1, 0x0E); + + /* Bypass VCO calibration */ + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SVS_MODE_CLK_SEL, + cfg.com_svs_mode_clk_sel); + + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_IVCO, 0x07); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_VCO_TUNE_CTRL, 0x00); + + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CLK_SEL, 0x30); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_HSCLK_SEL, + cfg.com_hsclk_sel); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP_EN, + cfg.com_lock_cmp_en); + + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_CCTRL_MODE0, + cfg.com_pll_cctrl_mode0); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_RCTRL_MODE0, + cfg.com_pll_rctrl_mode0); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CP_CTRL_MODE0, + cfg.com_cp_ctrl_mode0); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DEC_START_MODE0, + cfg.com_dec_start_mode0); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START1_MODE0, + cfg.com_div_frac_start1_mode0); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START2_MODE0, + cfg.com_div_frac_start2_mode0); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START3_MODE0, + cfg.com_div_frac_start3_mode0); + + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_INTEGLOOP_GAIN0_MODE0, + cfg.com_integloop_gain0_mode0); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_INTEGLOOP_GAIN1_MODE0, + cfg.com_integloop_gain1_mode0); + + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP1_MODE0, + cfg.com_lock_cmp1_mode0); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP2_MODE0, + cfg.com_lock_cmp2_mode0); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP3_MODE0, + cfg.com_lock_cmp3_mode0); + + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_VCO_TUNE_MAP, 0x00); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CORE_CLK_EN, + cfg.com_core_clk_en); + hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CORECLK_DIV_MODE0, + cfg.com_coreclk_div_mode0); + + /* TX lanes setup (TX 0/1/2/3) */ + for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(pll, i, + REG_HDMI_8998_PHY_TXn_DRV_LVL, + cfg.tx_lx_tx_drv_lvl[i]); + hdmi_tx_chan_write(pll, i, + REG_HDMI_8998_PHY_TXn_EMP_POST1_LVL, + cfg.tx_lx_tx_emp_post1_lvl[i]); + hdmi_tx_chan_write(pll, i, + REG_HDMI_8998_PHY_TXn_PRE_DRIVER_1, + cfg.tx_lx_pre_driver_1[i]); + hdmi_tx_chan_write(pll, i, + REG_HDMI_8998_PHY_TXn_PRE_DRIVER_2, + cfg.tx_lx_pre_driver_2[i]); + hdmi_tx_chan_write(pll, i, + REG_HDMI_8998_PHY_TXn_DRV_LVL_RES_CODE_OFFSET, + cfg.tx_lx_res_code_offset[i]); + } + + hdmi_phy_write(phy, REG_HDMI_8998_PHY_MODE, cfg.phy_mode); + + for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(pll, i, + REG_HDMI_8998_PHY_TXn_LANE_CONFIG, + 0x10); + } + + /* + * Ensure that vco configuration gets flushed to hardware before + * enabling the PLL + */ + wmb(); + + pll->rate = rate; + + return 0; +} + +static int hdmi_8998_phy_ready_status(struct hdmi_phy *phy) +{ + u32 nb_tries = HDMI_PLL_POLL_MAX_READS; + unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US; + u32 status; + int phy_ready = 0; + + while (nb_tries--) { + status = hdmi_phy_read(phy, REG_HDMI_8998_PHY_STATUS); + phy_ready = status & BIT(0); + + if (phy_ready) + break; + + udelay(timeout); + } + + return phy_ready; +} + +static int hdmi_8998_pll_lock_status(struct hdmi_pll_8998 *pll) +{ + u32 status; + int nb_tries = HDMI_PLL_POLL_MAX_READS; + unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US; + int pll_locked = 0; + + while (nb_tries--) { + status = hdmi_pll_read(pll, + REG_HDMI_8998_PHY_QSERDES_COM_C_READY_STATUS); + pll_locked = status & BIT(0); + + if (pll_locked) + break; + + udelay(timeout); + } + + return pll_locked; +} + +static int hdmi_8998_pll_prepare(struct clk_hw *hw) +{ + struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw); + struct hdmi_phy *phy = pll_get_phy(pll); + int i, ret = 0; + + hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x1); + udelay(100); + + hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x59); + udelay(100); + + ret = hdmi_8998_pll_lock_status(pll); + if (!ret) + return ret; + + for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(pll, i, + REG_HDMI_8998_PHY_TXn_LANE_CONFIG, 0x1F); + } + + /* Ensure all registers are flushed to hardware */ + wmb(); + + ret = hdmi_8998_phy_ready_status(phy); + if (!ret) + return ret; + + /* Restart the retiming buffer */ + hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x58); + udelay(1); + hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x59); + + /* Ensure all registers are flushed to hardware */ + wmb(); + + return 0; +} + +static long hdmi_8998_pll_round_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *parent_rate) +{ + if (rate < HDMI_PCLK_MIN_FREQ) + return HDMI_PCLK_MIN_FREQ; + else if (rate > HDMI_PCLK_MAX_FREQ) + return HDMI_PCLK_MAX_FREQ; + else + return rate; +} + +static unsigned long hdmi_8998_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw); + return pll->rate; +} + +static void hdmi_8998_pll_unprepare(struct clk_hw *hw) +{ + struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw); + struct hdmi_phy *phy = pll_get_phy(pll); + + hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0); + usleep_range(100, 150); +} + +static int hdmi_8998_pll_is_enabled(struct clk_hw *hw) +{ + struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw); + u32 status; + int pll_locked; + + status = hdmi_pll_read(pll, REG_HDMI_8998_PHY_QSERDES_COM_C_READY_STATUS); + pll_locked = status & BIT(0); + + return pll_locked; +} + +static const struct clk_ops hdmi_8998_pll_ops = { + .set_rate = hdmi_8998_pll_set_clk_rate, + .round_rate = hdmi_8998_pll_round_rate, + .recalc_rate = hdmi_8998_pll_recalc_rate, + .prepare = hdmi_8998_pll_prepare, + .unprepare = hdmi_8998_pll_unprepare, + .is_enabled = hdmi_8998_pll_is_enabled, +}; + +static const struct clk_init_data pll_init = { + .name = "hdmipll", + .ops = &hdmi_8998_pll_ops, + .parent_data = (const struct clk_parent_data[]){ + { .fw_name = "xo", .name = "xo_board" }, + }, + .num_parents = 1, + .flags = CLK_IGNORE_UNUSED, +}; + +int msm_hdmi_pll_8998_init(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct hdmi_pll_8998 *pll; + int ret, i; + + pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); + if (!pll) + return -ENOMEM; + + pll->pdev = pdev; + + pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll"); + if (IS_ERR(pll->mmio_qserdes_com)) { + DRM_DEV_ERROR(dev, "failed to map pll base\n"); + return -ENOMEM; + } + + for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) { + char name[32]; + + snprintf(name, sizeof(name), "hdmi_tx_l%d", i); + + pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name); + if (IS_ERR(pll->mmio_qserdes_tx[i])) { + DRM_DEV_ERROR(dev, "failed to map pll base\n"); + return -ENOMEM; + } + } + pll->clk_hw.init = &pll_init; + + ret = devm_clk_hw_register(dev, &pll->clk_hw); + if (ret) { + DRM_DEV_ERROR(dev, "failed to register pll clock\n"); + return ret; + } + + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &pll->clk_hw); + if (ret) { + DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret); + return ret; + } + + return 0; +} + +static const char * const hdmi_phy_8998_reg_names[] = { + "vddio", + "vcca", +}; + +static const char * const hdmi_phy_8998_clk_names[] = { + "iface", "ref", "xo", +}; + +const struct hdmi_phy_cfg msm_hdmi_phy_8998_cfg = { + .type = MSM_HDMI_PHY_8998, + .reg_names = hdmi_phy_8998_reg_names, + .num_regs = ARRAY_SIZE(hdmi_phy_8998_reg_names), + .clk_names = hdmi_phy_8998_clk_names, + .num_clks = ARRAY_SIZE(hdmi_phy_8998_clk_names), +}; diff --git a/drivers/gpu/drm/msm/registers/display/hdmi.xml b/drivers/gpu/drm/msm/registers/display/hdmi.xml index 6c81581016c78..1cf1b14fbd919 100644 --- a/drivers/gpu/drm/msm/registers/display/hdmi.xml +++ b/drivers/gpu/drm/msm/registers/display/hdmi.xml @@ -1012,4 +1012,93 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From patchwork Wed Jul 24 15:01:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Gonzalez X-Patchwork-Id: 814205 Received: from ns.iliad.fr (ns.iliad.fr [212.27.33.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D311112E71; Wed, 24 Jul 2024 15:02:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.27.33.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721833329; cv=none; b=Mf5TB8HcCdeRKE0gjx1GRwK5LUUf7JcLIZuelUIGblAlJjgqYWnXeRl4JIwwmEoFYW/A/I2afePG8UvQsbpds9IOLx3cyAiv6CkpAvYdEtjNdwSO07cNEWMfocZJhoj/XQuaudMHuN03C/XkaDiyrAyqLR7FzHSmNadwdLxTGQw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721833329; c=relaxed/simple; bh=UEpwc1sCiOSt7JHSYtQnKir00MQWhdJ0PXX7rkpvjJ8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JV0lOQKruWWj3kKPnXobXz2QUqChvS3BpTgDuLDw9rtWheuhAXM7wxF3JInOMF9PDo3pEPvAsg9qTsj07FFhhpcKAGFgh2+N6O+7O4knvOC50Jm7RTM2+n+1RKIapA2KFl2VZS5zlTpz9S0xoXgZXs6euE9eyhB92XmZx2ly6Wo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=freebox.fr; spf=pass smtp.mailfrom=srs.iliad.fr; arc=none smtp.client-ip=212.27.33.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=freebox.fr Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=srs.iliad.fr Received: from ns.iliad.fr (localhost [127.0.0.1]) by ns.iliad.fr (Postfix) with ESMTP id 49F3A2057C; Wed, 24 Jul 2024 17:01:55 +0200 (CEST) Received: from [127.0.1.1] (freebox.vlq16.iliad.fr [213.36.7.13]) by ns.iliad.fr (Postfix) with ESMTP id 0BF0520875; Wed, 24 Jul 2024 17:01:55 +0200 (CEST) From: Marc Gonzalez Date: Wed, 24 Jul 2024 17:01:38 +0200 Subject: [PATCH v7 5/6] arm64: dts: qcom: msm8998: add HDMI GPIOs Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240724-hdmi-tx-v7-5-e44a20553464@freebox.fr> References: <20240724-hdmi-tx-v7-0-e44a20553464@freebox.fr> In-Reply-To: <20240724-hdmi-tx-v7-0-e44a20553464@freebox.fr> To: Vinod Koul , Kishon Vijay Abraham I , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , David Airlie , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Bjorn Andersson , Konrad Dybcio Cc: linux-arm-msm@vger.kernel.org, linux-phy@lists.infradead.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, Arnaud Vrac , Pierre-Hugues Husson , Jeffrey Hugo , Marc Gonzalez X-Mailer: b4 0.13.0 MSM8998 GPIO pin controller reference design defines: - CEC: pin 31 - DDC: pin 32,33 - HPD: pin 34 Downstream vendor code for reference: https://git.codelinaro.org/clo/la/kernel/msm-4.4/-/blob/caf_migration/kernel.lnx.4.4.r38-rel/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi#L2324-2400 mdss_hdmi_{cec,ddc,hpd}_{active,suspend} Reviewed-by: Dmitry Baryshkov Signed-off-by: Marc Gonzalez --- arch/arm64/boot/dts/qcom/msm8998.dtsi | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi index e5f051f5a92de..ba5e873f0f35f 100644 --- a/arch/arm64/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi @@ -1434,6 +1434,34 @@ blsp2_spi6_default: blsp2-spi6-default-state { drive-strength = <6>; bias-disable; }; + + hdmi_cec_default: hdmi-cec-default-state { + pins = "gpio31"; + function = "hdmi_cec"; + drive-strength = <2>; + bias-pull-up; + }; + + hdmi_ddc_default: hdmi-ddc-default-state { + pins = "gpio32", "gpio33"; + function = "hdmi_ddc"; + drive-strength = <2>; + bias-pull-up; + }; + + hdmi_hpd_default: hdmi-hpd-default-state { + pins = "gpio34"; + function = "hdmi_hot"; + drive-strength = <16>; + bias-pull-down; + }; + + hdmi_hpd_sleep: hdmi-hpd-sleep-state { + pins = "gpio34"; + function = "hdmi_hot"; + drive-strength = <2>; + bias-pull-down; + }; }; remoteproc_mss: remoteproc@4080000 { From patchwork Wed Jul 24 15:01:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Gonzalez X-Patchwork-Id: 814636 Received: from ns.iliad.fr (ns.iliad.fr [212.27.33.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D30D99474; Wed, 24 Jul 2024 15:02:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.27.33.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721833328; cv=none; b=StolSus2DJd7G1BFNYwNP/1lIh2/zIr7zFVmzWO6aHBa5mHXliAM3xbBzZmAak7almApF26Pl0VR5b5BF4VcpcuYtBiYoJTLhNr135jJpWgYI6BX0GfCeCDhZwPSOI2UDndTnf2/IYn5viqjwyXcfyzBVNaST32IjTZZwL2uHHI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721833328; c=relaxed/simple; bh=Mojpcz4tfluA55WkjMI7U0USP3nVIzrabiETIoyZyLY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qnNIiGZ9u5CiC1ZcAGdN5+oViSClgWLcNRDArJxJk7/wNKmhCTHLBV6KXfmvh5ilQTQpyE/Lq01q6UOmDc4dhAAbhTYNm0xWKS5a+oMnXT2JYTDfGUUV5r7Kv6AXIuqG8PREWaYUlAQHo3XOEOrOUnZNcj6l/AVUfmHLl19HPCQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=freebox.fr; spf=pass smtp.mailfrom=srs.iliad.fr; arc=none smtp.client-ip=212.27.33.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=freebox.fr Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=srs.iliad.fr Received: from ns.iliad.fr (localhost [127.0.0.1]) by ns.iliad.fr (Postfix) with ESMTP id 49D2420572; Wed, 24 Jul 2024 17:01:55 +0200 (CEST) Received: from [127.0.1.1] (freebox.vlq16.iliad.fr [213.36.7.13]) by ns.iliad.fr (Postfix) with ESMTP id 1428F208F1; Wed, 24 Jul 2024 17:01:55 +0200 (CEST) From: Marc Gonzalez Date: Wed, 24 Jul 2024 17:01:39 +0200 Subject: [PATCH v7 6/6] arm64: dts: qcom: add HDMI nodes for msm8998 Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240724-hdmi-tx-v7-6-e44a20553464@freebox.fr> References: <20240724-hdmi-tx-v7-0-e44a20553464@freebox.fr> In-Reply-To: <20240724-hdmi-tx-v7-0-e44a20553464@freebox.fr> To: Vinod Koul , Kishon Vijay Abraham I , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , David Airlie , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Bjorn Andersson , Konrad Dybcio Cc: linux-arm-msm@vger.kernel.org, linux-phy@lists.infradead.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, Arnaud Vrac , Pierre-Hugues Husson , Jeffrey Hugo , Marc Gonzalez X-Mailer: b4 0.13.0 From: Arnaud Vrac Port device nodes from vendor code. Signed-off-by: Arnaud Vrac Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Marc Gonzalez --- arch/arm64/boot/dts/qcom/msm8998.dtsi | 100 +++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi index ba5e873f0f35f..1eb15e6d0af4a 100644 --- a/arch/arm64/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi @@ -2785,7 +2785,7 @@ mmcc: clock-controller@c8c0000 { <&mdss_dsi0_phy 0>, <&mdss_dsi1_phy 1>, <&mdss_dsi1_phy 0>, - <0>, + <&mdss_hdmi_phy 0>, <0>, <0>, <&gcc GCC_MMSS_GPLL0_DIV_CLK>; @@ -2890,6 +2890,14 @@ dpu_intf2_out: endpoint { remote-endpoint = <&mdss_dsi1_in>; }; }; + + port@2 { + reg = <2>; + + dpu_intf3_out: endpoint { + remote-endpoint = <&hdmi_in>; + }; + }; }; }; @@ -3045,6 +3053,96 @@ mdss_dsi1_phy: phy@c996400 { status = "disabled"; }; + + mdss_hdmi: hdmi-tx@c9a0000 { + compatible = "qcom,hdmi-tx-8998"; + reg = <0x0c9a0000 0x50c>, + <0x00780000 0x6220>, + <0x0c9e0000 0x2c>; + reg-names = "core_physical", + "qfprom_physical", + "hdcp_physical"; + + interrupt-parent = <&mdss>; + interrupts = <8>; + + clocks = <&mmcc MDSS_MDP_CLK>, + <&mmcc MDSS_AHB_CLK>, + <&mmcc MDSS_HDMI_CLK>, + <&mmcc MDSS_HDMI_DP_AHB_CLK>, + <&mmcc MDSS_EXTPCLK_CLK>, + <&mmcc MDSS_AXI_CLK>, + <&mmcc MNOC_AHB_CLK>, + <&mmcc MISC_AHB_CLK>; + clock-names = + "mdp_core", + "iface", + "core", + "alt_iface", + "extp", + "bus", + "mnoc", + "iface_mmss"; + + phys = <&mdss_hdmi_phy>; + #sound-dai-cells = <1>; + + pinctrl-0 = <&hdmi_hpd_default>, + <&hdmi_ddc_default>, + <&hdmi_cec_default>; + pinctrl-1 = <&hdmi_hpd_sleep>, + <&hdmi_ddc_default>, + <&hdmi_cec_default>; + pinctrl-names = "default", "sleep"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + hdmi_in: endpoint { + remote-endpoint = <&dpu_intf3_out>; + }; + }; + + port@1 { + reg = <1>; + hdmi_out: endpoint { + }; + }; + }; + }; + + mdss_hdmi_phy: hdmi-phy@c9a0600 { + compatible = "qcom,hdmi-phy-8998"; + reg = <0x0c9a0600 0x18b>, + <0x0c9a0a00 0x38>, + <0x0c9a0c00 0x38>, + <0x0c9a0e00 0x38>, + <0x0c9a1000 0x38>, + <0x0c9a1200 0x0e8>; + reg-names = "hdmi_pll", + "hdmi_tx_l0", + "hdmi_tx_l1", + "hdmi_tx_l2", + "hdmi_tx_l3", + "hdmi_phy"; + + #clock-cells = <0>; + #phy-cells = <0>; + + clocks = <&mmcc MDSS_AHB_CLK>, + <&gcc GCC_HDMI_CLKREF_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "iface", + "ref", + "xo"; + + status = "disabled"; + }; }; venus: video-codec@cc00000 {